ELIM Sexp Protocol (ESP): Daemon to Client calls

############################################################################
General Notes:

*) All calls come with an ID (a string) which should be returned as 
   part of the response. Not all calls require a response, but it
   should never cause problems to return a response that is not required.

*) Call IDs for daemon-to-client calls (and their corresponding responses)
   occupy a separate namespace than client-to-daemon calls: It is theoretically
   possible for a daemon-to-client call to have the same ID as a 
   client-to-daemon call, but this does not imply any relationship between 
   them.

############################################################################

Calls can usefully be divided into categories. The ones implemented so far are:

*) Account 
*) Buddy List (blist)
*) Connection
*) Conversation
*) Request

############################################################################

Account calls:

The calls in this group roughly correspond to those which notify you of 
changes to the state of IM accounts, they are:

*) elim-account-notify-added

   A buddy who is already on this account's buddy list added this account 
   (ie you) to their buddy list.
   NOTE: this would never actually happen on IRC, since IRC doesn't have 
   buddy lists as such, but you get the idea:

   Normally no user action would be required as a result of this notification.
   A client might wish to update its internal buddy list representation, though.

   (function-call nil
     (elim-account-notify-added ((id . "001")))
     (alist nil
       (string ((name . "user"        )) "rudybot"  )
       (string ((name . "alias"       )) "rudebot"  )
       (int    ((name . "account-uid" )) "268435456")
       (string ((name . "account-name")) "fsbot@irc.freenode.net")
       (string ((name . "im-protocol" )) "prpl-irc" )))

*) elim-account-status-changed

   The status (Available, Away etc) of an account changed
 
   (function-call nil
     (elim-account-notify-added ((id . "002")))
     (alist nil
       (int    ((name . "account-uid" )) "268435456")
       (string ((name . "account-name")) "fsbot@irc.freenode.net")
       (string ((name . "im-protocol" )) "prpl-irc" )
       (string ((name . "status-name" )) "Available")
       (int    ((name . "status-type" )) "2"        )
       (bool   ((name . "connected"   )) "0"        ) ))

*) elim-account-request-add

   A (potential) contact who is _not_ already in your buddy list added
   you to their buddy list.

   (function-call nil
     (elim-account-notify-added ((id . "003")))
     (alist nil
       (string ((name . "user"        )) "rudybot"  )
       (string ((name . "alias"       )) "rudebot"  )
       (string ((name . "message"     )) "rudebot added you: retaliate? (y/n)")
       (int    ((name . "account-uid" )) "268435456")
       (string ((name . "account-name")) "fsbot@irc.freenode.net")
       (string ((name . "im-protocol" )) "prpl-irc" )))
   
*) elim-account-request-auth

   Someone has performed an operation that requires authorisation from you.

   (function-call nil
     (elim-account-notify-added ((id . "004")))
     (alist nil
       (string ((name . "user"        )) "rudybot"      )
       (string ((name . "id"          )) "er, something")
       (string ((name . "alias"       )) "rudebot"      )
       (bool   ((name . "on-list"     )) "0"            )
       (string ((name . "message"     )) "rudebot added you: retaliate? (y/n)")
       (int    ((name . "account-uid" )) "268435456")
       (string ((name . "account-name")) "fsbot@irc.freenode.net")
       (string ((name . "im-protocol" )) "prpl-irc" )))
    
on-list: whether the other user is on your buddy list already

   (function-response 
     (elim-account-notify-added ((id . "004")))
     (alist nil
       (int  ((name . "status")) "0") 
       (bool ((name . "value" )) "1")))

The response indicates whether you should accept (bool 1) or reject (bool 0)
the request.
############################################################################

Blist calls:

These are concerned with changes to your buddy list:

Some terminology:

A "buddy"   is a contact, typically another IM user.
A "contact" is slightly different: a contact is a logical grouping of 
            buddies. For example, if you have two different sets of 
            IM details for one person (eg on different IM networks)
            You might place them in a contact together.
A "group"   Is a logical group into which you can place a buddy
            or contact. Some protocols support groups on the server,
            others leave it entirely up to clients.
            The default group is "Buddies" for buddies and contacts
            And "Chats" for multi-user rooms/chats/channels/

The main calls here (there are other but they are not implemented yet)
Have very similar return structures: Some details are simple omitted 
for those blist node types which do not support them:

*) elim-blist-new-node

   This call informs you that a new node has been created. However,
   investigation of the libpurple code reveaks that this means a 
   new node has been allocated, but _not_ that it has been added to 
   the buddy list... so in general you don;t have to do anything
   when you see this.

*) elim-blist-update-node

   A node was added to the buddy list and/or changed

*) elim-blist-remove-node

  A node was removed from the buddy list

Some of the fields require clarification:

bnode-type  : an integer specifying the type of node: see be,ow for details
bnode-parent: if this node is contained within another node, the uid
              of the container is given here.
bnode-child : if this node contains other nodes, the uid of the first child
              node will be given here
bnode-prev  : the preceding sibling node, if any
bnode-next  : the subsequent sibling node, if any
bnode-flags : usually uninteresting. if (logand flags 1), then the node
              is ephemeral and should not be saved.
allowed     : false if you have blocked this IM user
status-id   : canonical IM status ID
status-name : human friendly status name
status-type : status type code - what type of status is this.
status-msg  : extended status message

A buddy:

   (function-call nil 
     (elim-blist-update-node ((id . "010")))
     (alist nil
       (int    ((id . "bnode-uid"    )) "268435500")
       (int    ((id . "bnode-type"   )) "2"        )
       (string ((id . "bnode-name"   )) "fsbot"    )
       (int    ((id . "account-uid"  )) "268435456")
       (string ((id . "account-name" )) "elim@irc.freenode.net")
       (string ((id . "im-protocol"  )) "prpl-im"  )
       (string ((id . "bnode-alias"  )) "fsbot"    )
       (string ((id . "server-alias" )) "fsbot"    )
       (string ((id . "contact-alias")) "erbot"    )
       (string ((id . "bnode-prev"   )) "126346445")
       (string ((id . "bnode-next"   )) "126313246")
       (string ((id . "bnode-parent" )) "133313123")
       (string ((id . "bnode-child"  )) "216313141")
       (string ((id . "bnode-flags"  )) "0"        )
       (bool   ((id . "allowed"      )) "1"        )
       (bool   ((id . "available"    )) "0"        )
       (bool   ((id . "online"       )) "1"        )
       (bool   ((id . "idle"         )) "1"        )
       (string ((id . "status-name"  )) "Away"     )
       (string ((id . "status-id"    )) "away"     )
       (int    ((id . "status-type"  )) "5"        )
       (string ((id . "status-msg"   )) "Off to lunch") ))

A chat node (channel, room, etc):

   (function-call nil 
     (elim-blist-update-node ((id . "010")))
     (alist nil
       (int    ((id . "bnode-uid"    )) "268435500")
       (int    ((id . "bnode-type"   )) "3"        )
       (string ((id . "bnode-name"   )) "fsbot"    )
       (int    ((id . "account-uid"  )) "268435456")
       (string ((id . "account-name" )) "elim@irc.freenode.net")
       (string ((id . "im-protocol"  )) "prpl-im"  )
       (string ((id . "bnode-prev"   )) "126346445")
       (string ((id . "bnode-next"   )) "126313246")
       (string ((id . "bnode-parent" )) "133313123")
       (string ((id . "bnode-child"  )) "216313141")
       (string ((id . "bnode-flags"  )) "0"        )
       (bool   ((id . "allowed"      )) "1"        ) ))

A Contact node:

   (function-call nil 
     (elim-blist-update-node ((id . "010")))
     (alist nil
       (int    ((id . "bnode-uid"    )) "268435500")
       (int    ((id . "bnode-type"   )) "1"        )
       (string ((id . "bnode-name"   )) "fsbot"    )
       (string ((id . "bnode-prev"   )) "126346445")
       (string ((id . "bnode-next"   )) "126313246")
       (string ((id . "bnode-parent" )) "133313123")
       (string ((id . "bnode-child"  )) "216313141")
       (string ((id . "bnode-flags"  )) "0"        ) ))

A group node:

   (function-call nil 
     (elim-blist-update-node ((id . "010")))
     (alist nil
       (int    ((id . "bnode-uid"    )) "268435500" )
       (int    ((id . "bnode-type"   )) "0"         )
       (string ((id . "bnode-name"   )) "fsbot"     )
       (string ((id . "bnode-prev"   )) "126346445" )
       (string ((id . "bnode-next"   )) "126313246" )
       (string ((id . "bnode-parent" )) "133313123" )
       (string ((id . "bnode-child"  )) "216313141" )
       (string ((id . "bnode-flags"  )) "0"         ) ))

############################################################################

Connection calls:

