XMPP For The Web/Win ::: XMPP-FTW (1.18.0) Flattr this

Buddycloud extension for XMPP-FTW

Buddycloud is a open source/standards federated social network built on top of XMPP. For more information about the future of social networking please see the buddycloud website.

Discover buddycloud server

The first thing you must do is to discover your buddycloud server. Any attempted actions before the discovery will result in an error response.

socket.send(
    'xmpp.buddycloud.discover',
    { /* "server": "channels.buddycloud.org" */ },
    function(error, data) { console.log(error, data) }
)

If a server is discovered the `data` will contain the channel server host, if not `error` will be populated to tell you that no server was found.

Providing a `server` key allows the user to short cut discovery by specifying the channel server they wish to use.

There is a default timeout of 8 seconds on the second part of the discovery process (where we ask components for features/identity). If a server is found before this time then xmpp-ftw will inform you immediately. This value can be changed server-side by calling the

setDiscoveryTimeout
method on a Buddycloud object.

Disco requests

For convenience, `xmpp-ftw-buddycloud` proxies disco requests for the user using the two events xmpp.buddycloud.discover.items and xmpp.buddycloud.discover.info ( xmpp.discover.items and xmpp.discover.info respectively).

These events are documented in service discovery. Note: these events do not require that the channel server is discovered first.

Presence

Presence must be sent to the buddycloud server in order to start receiving notifications. Default presence is set as 'online' with a priority of -1, and a status of 'buddycloud'.

For more advanced priority setting it is suggested that you use 'xmpp.presence'.

socket.send('xmpp.buddycloud.presence', {})

Registration

The first time you use a buddycloud server you should register with it in order to generate your personal nodes. Multiple registrations will not cause an error.

socket.send(
    'xmpp.buddycloud.register',
    {},
    function(error, data) { console.log(error, data) }
)

A successful response will look as follows:

{ registered: true }

In the unlikely event of an error upon registration these will formatted in the same style as xmpp-ftw-register.

Create a node

socket.send(
    'xmpp.buddycloud.create',
    {
        "node": "/user/weather@topics.evilprofessor.co.uk/posts",
     /* "options": [] */
    },
    function(error, data) { console.log(error, data) }
)

options should be formatted as a data form in order to add node configuration options at creation time.

If the node is successfully created `error` will be null and `data` will be true.

Deleting a node is covered later

Publishing to a node

socket.send(
    'xmpp.buddycloud.publish',
    {
        "node": "/user/lloyd@buddycloud.org/posts",
        "content": {
            "atom": {
                "content": "Posting from XMPP-FTW"
            },
            "in-reply-to": { "ref": "1234-5678-9087-6543" }
        }
    },
    function(error, data) { console.log(error, data) }

A successful post will result in the following response:

{
    "id": "tag:null@channels.evilprofessor.co.uk,/user/lloyd@evilprofessor.co.uk/posts,1"
}

Subscriptions

Subscribe to a node

socket.send(
    'xmpp.buddycloud.subscribe',
    {
        "node": "/user/lloyd@buddycloud.org/posts"
    },
    function(error, data) { console.log(error, data) }
)

If a subscription is successful then the value of `data` will be as follows:

{
    subscription: "subscribed"
}

Unsubscribe from a node

socket.send(
    'xmpp.buddycloud.unsubscribe',
    {
        "node": "/user/lloyd@buddycloud.org/posts"
    },
    function(error, data) { console.log(error, data) }
)

If there is no `error` then `data` will simply be true.

Get subscriptions

This method supports RSM.

socket.send(
    'xmpp.buddycloud.subscriptions',
    {
     /* "node": "/user/weather@topics.evilprofessor.co.uk/posts", */
     /* "owner": true, */
     /* "ephemeral": true */
    },
    function(error, data) { console.log(error, data) }
)

Setting owner to true will return information about all subscriptions to that node. This is provided you are the owner of the node, otherwise an error will be returned.

Setting ephemeral to true will retrieve subscriptions from ephemeral nodes only. Leaving it out will default to non-ephemeral nodes only. Note: This only applies to user subscriptions.

A successful response will then be as follows:

[
    {
        node: "/user/lloyd@evilprofessor.co.uk/posts",
        jid: { user: "lloyd", domain: "evilprofessor.co.uk" },
        subscription: "subscribed"
    },
    {
        node: "/user/megan@evilprofessor.co.uk/posts",
        jid: { user: "lloyd", domain: "evilprofessor.co.uk" },
        subscription: "pending"
    },
    {
        node: "/user/lloyd@evilprofessor.co.uk/posts",
        jid: { user: "megan", domain: "evilprofessor.co.uk" },
        invitedBy: { user: "lloyd", domain: "evilprofessor.co.uk" },
        subscription: "invited"
    }
]

Updating a subscribers subscription

As a node owner, or moderator, it is also possible to update the subscription state of a user as follows:

socket.send(
    'xmpp.buddycloud.subscription',
    {
        "node":          "/user/lloyd@evilprofessor.co.uk/posts",
        "jid":           "bad-person@evilprofessor.co.uk",
        "subscription" : "none"
    },
    function(error, data) { console.log(error, data) }
)

On success the data argument will simply be true.

Inviting a user to a node

As a subscriber it is possible to invite another user to a node as follows:

socket.send(
    'xmpp.buddycloud.subscription',
    {
        "node":          "/user/lloyd@evilprofessor.co.uk/posts",
        "jid":           "megan@evilprofessor.co.uk",
        "subscription" : "invited"
    },
    function(error, data) { console.log(error, data) }
)

On success the data argument will simply be true.

Notification of a subscription change

In the event of a subscription change all node subscribers are informed via the `xmpp.buddycloud.push.subscription` event:

{
    node: "/user/weather@topics.evilprofessor.co.uk/posts",
    jid: {
        domain: "evilprofessor.co.uk",
        user: "megan"
    },
    subscription: "subscribed",
 /* invitedBy: {
        domain: "evilprofessor.co.uk",
        user: "lloyd"
    } */
}

Subscription authorisation request

If required, and if supported by the server, a node owner, or moderator, will receive a subscription authorisation request as follows:

socket.on('xmpp.buddycloud.push.authorisation', function(data, callback) {
    console.log(data)
    callback( /* see below */ )
})

With the data in the following format:

{
    id: "approve1",
    form: {}
}

In order to reply to a subscription authorisation request the callback function should be used as follows (actual field data will depend on received data form):

[
    { var: "pubsub#node", value: "/user/lloyd@evilprofessor.co.uk/posts" },
    { var: "pubsub#subscriber_jid": value: "megan@evilprofessor.co.uk" },
    { var: "pubsub#allow", value: "true" }
]

Affiliations

Get node affiliations

This method supports RSM.

socket.send(
    'xmpp.buddycloud.affiliations',
    {
     /* "node": "/user/lloyd@evilprofessor.co.uk/posts", */
     /* "owner": true", */
     /* "ephemeral": true */
    },
    function(error, data) { console.log(error, data) }
)

Setting owner to true allows the user to get a list of all node affiliations provided they are the owner of the node (otherwise an error is returned.

Setting ephemeral to true will retrieve affiliations from ephemeral nodes only. Leaving it out will default to non-ephemeral nodes only. Note: This only applies to user affiliations.

A successful response will then be as follows:

[
   {
        jid: { user: "lloyd", domain: "evilprofessor.co.uk" },
        affiliation: 'owner'
   },
   {
        jid: { user: "dev-kitty-1", domain: "evilprofessor.co.uk" },
        affiliation: 'member'
   }
]

Set node affiliation

socket.send(
    'xmpp.buddycloud.affiliation',
    {
        "node": "/user/lloyd@evilprofessor.co.uk/posts",
        "jid": "troll@underthebrid.ge",
        "affiliation": "outcast"
    },
    function(error, data) { console.log(error, data) }
)

If the node is successfully created `error` will be null and `data` will be true.

Note: Whilst specification allows user to update several affiliation changes at once, only on per message is supported here. If required it can be added later.

Notification of affiliation changes

The event name for these changes is `xmpp.buddycloud.push.affiliation`.

{
    node: "/user/lloyd@evilprofessor.co.uk/posts",
    jid: {
        domain: "evilprofessor.co.uk",
        user: "bad-person"
    },
    affiliation: "none"
}

Items

Retrieve items

Retrieve items from a buddycloud node. For information about how RSM is supported please see result set management.

socket.send(
    'xmpp.buddycloud.retrieve',
    {
        "node": "/user/lloyd@buddycloud.org/posts",
     /* "id": "1234-5678-9012", */
     /* "parentOnly": false */
    },
    function(error, data) { console.log(error, data) }
)

Items are parsed using `xmpp-ftw-item-parser` although it is possible to inject your own parser. Additonal features of the item will be come available as this project adds support.

Unlike `xmpp-ftw-pubsub` items will always include a node key. parentOnly retrieves only the first post in each thread and does not include any replies.

Notification of new messages

When an item is published to a node that your user is subscribed to then a message will be received with item details.

socket.on('xmpp.buddycloud.push.item', function(data) {
    console.log(data)
})

The item itself is parsed by `xmpp-ftw-item-parser` and is held in the item key.

{
    from: 'channels.evilprofessor.co.uk',
    node: '/user/weather@server.com/posts',
    id:   '201305301825',
    item: ...as parsed by xmpp-ftw-item-parser...
}

Retrieve recent items

Retrieve recent items for subscribed nodes by requesting using the following event name (this message supports RSM):

socket.send(
    'xmpp.buddycloud.items.recent',
    {
      /* "max": 50, */
      /* "since": "2013-07-01 16:02:00", */
      /* "parentOnly": true */
    },
    function(error, data, rsm) { console.log(error, data, rsm) }
)

Whilst both max and since are optional it is suggested values are provided. max will default to 30 if not set, whilst since will default to 1st January 2000 if not set. since will accept any string which can be parsed by Date.parse(). Setting parentOnly with something that evaluates to true will request only thread parents.

Output data has the following format:

[
    {
        node: '/user/lloyd@evilprofessor.co.uk/posts',
        id: 'item-1',
        entry: //... a parsed by xmpp-ftw-item-parser ...//
    },
    {
        node: '/user/megan@evilprofessor.co.uk/posts',
        id: 'item-3',
        entry: //... a parsed by xmpp-ftw-item-parser ...//
    },
    {
        node: '/user/lloyd@evilprofessor.co.uk/posts',
        id: 'item-5',
        entry: //... a parsed by xmpp-ftw-item-parser ...//
    },

]

Retrieve user feed

Very similar to the recent items retrieval, except that it does not attempt to retrieve items from every channel regardless of age. This function returns a feed as if all items are in a single feed (this message supports RSM):

socket.send(
    'xmpp.buddycloud.items.feed',
    {
      /* "since": "2013-07-01 16:02:00", */
      /* "parentOnly": true */
    },
    function(error, data, rsm) { console.log(error, data, rsm) }
)

Whilst since are optional it is suggested the value is provided. since will default to 1st January 2000 if not set. since will accept any string which can be parsed by Date.parse(). Setting parentOnly with something that evaluates to true will request only thread parents.

Output data has the following format:

[
    {
        node: '/user/lloyd@evilprofessor.co.uk/posts',
        id: 'item-1',
        entry: //... a parsed by xmpp-ftw-item-parser ...//
    },
    {
        node: '/user/megan@evilprofessor.co.uk/posts',
        id: 'item-3',
        entry: //... a parsed by xmpp-ftw-item-parser ...//
    },
    {
        node: '/user/lloyd@evilprofessor.co.uk/posts',
        id: 'item-5',
        entry: //... a parsed by xmpp-ftw-item-parser ...//
    },

]

Item Thread

Retrieve a full post thread as follows (RSM supported):

socket.send(
    'xmpp.buddycloud.items.thread',
    {
        "node": "/user/lloyd@evilprofessor.co.uk/posts",
        "id": "1234-5678-9012-3456"
    },
    function(error, data, rsm) { console.log(error, data, rsm) }
)

Responses then look like the following:

[
    {
        id: '1234-5678-9012-3457',
        node: "/user/lloyd@evilprofessor.co.uk/posts",
        entry: //... as parsed by xmpp-ftw-item-parser ...//
    }
]

Item Replies

Retrieve all replies to a post as follows (RSM supported):

socket.send(
    'xmpp.buddycloud.items.replies',
    {
        "node": "/user/lloyd@evilprofessor.co.uk/posts",
        "id": "1234-5678-9012-3456"
    },
    function(error, data, rsm) { console.log(error, data, rsm) }
)

Responses then look like the following:

[
    {
        id: '1234-5678-9012-3457',
        entry: //... as parsed by xmpp-ftw-item-parser ...//
        node: "/user/lloyd@evilprofessor.co.uk/posts",
    }
]

Delete an item

socket.send(
    'xmpp.buddycloud.item.delete',
    {
        "node": "/user/lloyd@buddycloud.org/posts",
        "id": "1"
    },
    function(error, data) { console.log(error, data) }
)

If the delete is successful then `data` will simply be true.

Item deletion notification

If an item is successfully deleted from a node then all subscribers will be notified of this event (configuration dependent).

socket.on('xmpp.buddycloud.push.retract', function(data) {
    console.log(data)
})

With the payload as follows:

{
    node: '/user/weather@topics.evilprofessor.co.uk/posts',
    id: '222'
}

Configuring a node

Node configuration follows that of the standard pubsub setup with simply the event name changed.

Get node configuration

socket.send(
    'xmpp.buddycloud.config.get',
    {
        "node": "/user/weather@topics.evilprofessor.co.uk/posts"
    },
    function(error, data) { console.log(error, data) }
)

Set node configuration

socket.send(
    'xmpp.buddycloud.config.set',
    {
        "node": "/user/weather@topics.evilprofessor.co.uk/posts",
        "form": []
    },
    function(error, data) { console.log(error, data) }
)

If configuration update is sucessful then `data` will simply be true.

Node configuration update notification

On update of a node's configuration then a notification will be sent to all node subscribers.

socket.on('xmpp.buddycloud.push.configuration', function(data) {
    console.log(data)
})

With data looking as follows:

{
    node: '/user/weather@topics.evilprofessor.co.uk/posts',
    configuration: []
}

configuration if provided will match the parsing of other data forms.

Deleting a node

socket.send(
    'xmpp.buddycloud.delete',
    {
        "node": "/user/lloyd@buddycloud.org/posts"
    },
    function(error, data) { console.log(error, data) }
)

If the delete is successful then `data` will simply be true.

Item deletion notification

If a node is successfully deleted then all subscribers will be notified of this event (configuration dependent).

socket.on('xmpp.buddycloud.push.delete', function(data) {
    console.log(data)
})

With the payload as follows:

{
    node: '/user/weather@topics.evilprofessor.co.uk/posts'
}

Discovering media servers

Media servers can be discovered using the method below. Domain is the domain on which the channel you wish to post to lives. Note: If you are attempting to post to a topic channel you will need to run the discovery against the parent domain (usually a case of just removing the subdomain).

socket.send(
    'xmpp.buddycloud.discover.media-server',
    {
        "of": "evilprofessor.co.uk"
    },
    function(error, data) { console.log(error, data) }
)

If a media server component can not be found then the error message will be an item-not-found error. A successful response is as follows:

{
    component: 'media.evilprofessor.co.uk',
 /* endpoint: 'https://api.evilprofessor.co.uk/media' */
}

The endpoint will only be provided if the media server advertises it.

There is a default timeout of 10 seconds on the second part of the media server discovery process (where we ask components for features/identity). If a server is found before this time then xmpp-ftw will inform you immediately. This value can be changed server-side by calling the

setMediaServerDiscoveryTimeout
method on a Buddycloud object.

Verifying HTTP requests

If a media server has been discovered then xmpp-ftw-buddycloud will take over handling of HTTP verification requests from this server.

The HTTP verfication is detailed on the manual page and here we simply show the related events.

An incoming verification request is picked up as follows:

socket.on(
    'xmpp.buddycloud.http.verify',
    function(data) { console.log(data) }
)

This request can then either be confirmed or denied as follows. Approve:

socket.send(
    'xmpp.buddycloud.http.confirm',
    { 
        "to": "media.evilprofessor.co.uk",
        "id": "abc-123",
        "type": "iq",
        "request": {
            "url": "https://media.evilprofessor.co.uk/secret.txt",
            "method": "GET",
            "id": "request-1"
        }

    },
    function(error, data) { console.log(error, data) }
)

Deny:

socket.send(
    'xmpp.buddycloud.http.deny',
    { 
        "to": "media.evilprofessor.co.uk",
        "id": "abc-123",
        "type": "iq",
        "request": {
            "url": "https://media.evilprofessor.co.uk/secret.txt",
            "method": "GET",
            "id": "request-1"
        }

    },
    function(error, data) { console.log(error, data) }
)

Pages

Fork me on GitHub