Tkabber Wiki

How to add a new remote command
Login

Since September 18, 2006 Tkabber supports remote control [1]. We tried to make it as extensible as other parts of Tkabber. Also remember that controlling acts per Ad-Hoc commands [2] and other side must supports it. At this moment you can control Tkabber from Tkabber, Psi and Bombus. Other clients aren't tried yet.

You'll learn from this article how to create and register your own function for remote control.

Contents

Understanding

Ok. If you are ready let's try to understand base blocks of remote control internals.

There is a base engine. It does the following things:

  1. It remembers all registered commands and announces them via Disco.
  2. It creates and tracks opened sessions and makes memory cleanup after closing them.
  3. It applies filter rules to incoming ad-hoc and disco queries.
  4. And it also does some simple checks (each stanza with one sessionid must arrive from one jid and with one node, the node must exists (be registered) and so on).

That's all the base engine does. Other things (parse and create x:data forms, track completed steps and passed values in one session, do finally action and so on) must be done by specific remote command. But don't despair. There are still several things that has beed already automated.

Coding

First you should name your remote command and select a node. For example a suitable name for change_status could be "Change status" and hence the node will be "http://jabber.org/protocol/rc#set-status" as specified in the JEP-0146. After having done that you should imagine how it should work, which forms it would show and what it would finally do.

Registering your remote command

It's simple:

::remote::register_command "place_node_name_here" \
                          [namespace current]::myplugin::rc_handler "My function"

and rc_handler must be defined as follow:

proc myplugin::rc_handler {session action children} {
  ...
}

Scheduler

Ok, now we have registered our node with specified caption and have an empty handler wich will be called on each incoming query to our command. Let's think what we have to do in the remain. We should N times create form and parse results. When N=0 we have the simplest case when we don't need any data from user for doing the action. When N=1 there is more complex case with one form. And when N>1 we have so called wizard. In each case at the end we do finall action and return some sort of successfull message. Let's each pair of creating and parsing a form call step. So we have to implement N steps and a finall action.

If common scheme is clear, let's detail it:

  1. When first query to our command arrives we should:
    • check is action correct (execute or empty)
    • save to session hash that we are in step 1
    • create first form and return it as answer
  2. When N query arrives and N-1 not equal number of total connections:
    • check is action correct (next or empty)
    • parse result for N-1 form
    • store gathered data into the session hash
    • increment step in the session hash
    • create N form and return it as answer
  3. When N query arrives and N-1 is last step:
    • check is action correct (complete)
    • parse result for N-1 (last) form
    • do action
    • return some sort of successfull message as answer

This algoritm will work if user just clicks Next, Next, Next ... Complete. If he'll use Prev or Cancel we have to might revert to the previous step and clear data from each step or all data whithout doing finall action.

There is enough to implement, isn't there? Good news. Some part already is implemented in the ::remote::standart_schedueler. This procedure will take care of steps and actions. To use it you should call it from you handler:

proc myplugin::rc_handler {session action children} {
    return [::remote::standart_scheduler 1 "[namespace current]::" $session $action $children]
}

The first param is a total number of steps. The second is a prefix. Typically it is your namspace where you must create three procedures for each step and one for finall action. It will be described in the next sections.

Steps

Ok, now we don't need to bother about steps, action, sessionid and disco queries. We just need to create forms, parse results and do a finall action.

For each step you need to create three procedures:

Last step

Sending errors

Cleanup

Read sources!

You can find an example of working code in the plugins/general/remote.tcl file. The first part of it is the base engine. After it you can find implementation of change status, leave groupchats and forward unread messages functions. Change status is the easiest thing for understanding.

See also

  1. JEP-0146: Remote Controlling Clients
  2. JEP-0050: Ad-Hoc Commands
  3. JEP-0004: Data Forms