浏览代码

Write documentation for the archive API. Also add another test.

update #306
JC Brand 10 年之前
父节点
当前提交
69de033cea
共有 2 个文件被更改,包括 173 次插入11 次删除
  1. 144 11
      docs/source/development.rst
  2. 29 0
      spec/mam.js

+ 144 - 11
docs/source/development.rst

@@ -51,14 +51,14 @@ directory:
 On Windows you need to specify Makefile.win to be used by running: ::
 On Windows you need to specify Makefile.win to be used by running: ::
 
 
     make -f Makefile.win dev
     make -f Makefile.win dev
-    
+
 Or alternatively, if you don't have GNU Make:
 Or alternatively, if you don't have GNU Make:
 
 
 ::
 ::
 
 
     npm install
     npm install
     bower update
     bower update
-    
+
 This will first install the Node.js development tools (like Grunt and Bower)
 This will first install the Node.js development tools (like Grunt and Bower)
 and then use Bower to install all of Converse.js's front-end dependencies.
 and then use Bower to install all of Converse.js's front-end dependencies.
 
 
@@ -125,7 +125,7 @@ Please read the `style guide </docs/html/style_guide.html>`_ and make sure that
 Add tests for your bugfix or feature
 Add tests for your bugfix or feature
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 Add a test for any bug fixed or feature added. We use Jasmine
 Add a test for any bug fixed or feature added. We use Jasmine
-for testing. 
+for testing.
 
 
 Take a look at `tests.html <https://github.com/jcbrand/converse.js/blob/master/tests.html>`_
 Take a look at `tests.html <https://github.com/jcbrand/converse.js/blob/master/tests.html>`_
 and the `spec files <https://github.com/jcbrand/converse.js/blob/master/tests.html>`_
 and the `spec files <https://github.com/jcbrand/converse.js/blob/master/tests.html>`_
@@ -146,7 +146,7 @@ Developer API
         Earlier versions of Converse.js might have different API methods or none at all.
         Earlier versions of Converse.js might have different API methods or none at all.
 
 
 In the Converse.js API, you traverse towards a logical grouping, from
 In the Converse.js API, you traverse towards a logical grouping, from
-which you can then call certain standardised accessors and mutators, like::
+which you can then call certain standardised accessors and mutators, such as::
 
 
     .get
     .get
     .set
     .set
@@ -202,6 +202,139 @@ Example:
             roster_groups: true
             roster_groups: true
         });
         });
 
 
+The "archive" grouping
+----------------------
+
+Converse.js supports the *Message Archive Management*
+(`XEP-0313 <https://xmpp.org/extensions/xep-0313.html>`_) protocol,
+through which it is able to query an XMPP server for archived messages.
+
+query
+~~~~~
+
+The ``query`` method is used to query for archived messages.
+
+It accepts the following optional parameters:
+
+* **options** an object containing the query parameters. Valid query parameters
+  are ``with``, ``start``, ``end``, ``first``, ``last``, ``after``, ``before``, ``index`` and ``count``.
+* **callback** is the callback method that will be called when all the messages
+  have been received.
+* **errback** is the callback method to be called when an error is returned by
+  the XMPP server, for example when it doesn't support message archiving.
+
+Examples
+^^^^^^^^
+
+**Requesting all archived messages**
+
+The simplest query that can be made is to simply not pass in any parameters.
+Such a query will return all archived messages for the current user.
+
+Generally, you'll however always want to pass in a callback method, to receive
+the returned messages.
+
+.. code-block:: javascript
+
+    var errback = function (iq) {
+        // The query was not successful, perhaps inform the user?
+        // The IQ stanza returned by the XMPP server is passed in, so that you
+        // may inspect it and determine what the problem was.
+    }
+    var callback = function (messages) {
+        // Do something with the messages, like showing them in your webpage.
+    }
+    converse.archive.query(callback, errback))
+
+
+**Requesting all archived messages for a particular contact or room**
+
+To query for messages sent between the current user and another user or room,
+the query options need to contain the the JID (Jabber ID) of the user or
+room under the  ``with`` key.
+
+.. code-block:: javascript
+
+    // For a particular user
+    converse.archive.query({'with': 'john@doe.net'}, callback, errback);)
+
+    // For a particular room
+    converse.archive.query({'with': 'discuss@conference.doglovers.net'}, callback, errback);)
+
+
+**Requesting all archived messages before or after a certain date**
+
+The ``start`` and ``end`` parameters are used to query for messages
+within a certain timeframe. The passed in date values may either be ISO8601
+formatted date strings, or Javascript Date objects.
+
+.. code-block:: javascript
+
+    var options = {
+        'with': 'john@doe.net',
+        'start': '2010-06-07T00:00:00Z',
+        'end': '2010-07-07T13:23:54Z'
+    };
+    converse.archive.query(options, callback, errback);
+
+
+**Limiting the amount of messages returned**
+
+The amount of returned messages may be limited with the ``max`` parameter.
+By default, the messages are returned from oldest to newest.
+
+.. code-block:: javascript
+
+    // Return maximum 10 archived messages
+    converse.archive.query({'with': 'john@doe.net', 'max':10}, callback, errback);
+
+
+**Paging forwards through a set of archived messages**
+
+When limiting the amount of messages returned per query, you might want to
+repeatedly make a further query to fetch the next batch of messages.
+
+To simplify this usecase for you, the callback method receives not only an array
+with the returned archived messages, but also a special RSM (*Result Set
+Management*) object which contains the query parameters you passed in, as well
+as two utility methods ``next``, and ``previous``.
+
+When you call one of these utility methods on the returned RSM object, and then
+pass the result into a new query, you'll receive the next or previous batch of
+archived messages.
+
+.. code-block:: javascript
+
+    var callback = function (messages, rsm) {
+        // Do something with the messages, like showing them in your webpage.
+        // ...
+        // You can now use the returned "rsm" object, to fetch the next batch of messages:
+        converse.archive.query(rsm.next(), callback, errback))
+
+    }
+    converse.archive.query({'with': 'john@doe.net', 'max':10}, callback, errback);
+
+**Paging backwards through a set of archived messages**
+
+To page backwards through the archive, you need to know the UID of the message
+which you'd like to page backwards from and then pass that as value for the
+``before`` parameter. If you simply want to page backwards from the most recent
+message, pass in the ``before`` parameter with a value of ``null``.
+
+.. code-block:: javascript
+
+    converse.archive.query({'before': null, 'max':5}, function (message, rsm) {
+        // Do something with the messages, like showing them in your webpage.
+        // ...
+        // You can now use the returned "rsm" object, to fetch the previous batch of messages:
+        rsm.previous(); // Call previous method, to update the object
+                        // parameters so that the previous batch of messages will be returned.
+        rsm.count = 10; // Increase the page size (currently it's set to 1,
+                        // because that was what we specified in our last query.
+        // Now we query again, to get the previous batch.
+        converse.archive.query(rsm, callback, errback);
+    }
+
 
 
 The "user" grouping
 The "user" grouping
 -------------------
 -------------------
@@ -213,7 +346,7 @@ logout
 
 
 Log the user out of the current XMPP session.
 Log the user out of the current XMPP session.
 
 
-.. code-block:: javascript 
+.. code-block:: javascript
 
 
     converse.user.logout();
     converse.user.logout();
 
 
@@ -228,7 +361,7 @@ get
 
 
 Return the current user's availability status:
 Return the current user's availability status:
 
 
-.. code-block:: javascript 
+.. code-block:: javascript
 
 
     converse.user.status.get(); // Returns for example "dnd"
     converse.user.status.get(); // Returns for example "dnd"
 
 
@@ -246,7 +379,7 @@ The user's status can be set to one of the following values:
 
 
 For example:
 For example:
 
 
-.. code-block:: javascript 
+.. code-block:: javascript
 
 
     converse.user.status.set('dnd');
     converse.user.status.set('dnd');
 
 
@@ -254,7 +387,7 @@ Because the user's availability is often set together with a custom status
 message, this method also allows you to pass in a status message as a
 message, this method also allows you to pass in a status message as a
 second parameter:
 second parameter:
 
 
-.. code-block:: javascript 
+.. code-block:: javascript
 
 
     converse.user.status.set('dnd', 'In a meeting');
     converse.user.status.set('dnd', 'In a meeting');
 
 
@@ -264,7 +397,7 @@ The "message" sub-grouping
 The ``user.status.message`` sub-grouping exposes methods for setting and
 The ``user.status.message`` sub-grouping exposes methods for setting and
 retrieving the user's custom status message.
 retrieving the user's custom status message.
 
 
-.. code-block:: javascript 
+.. code-block:: javascript
 
 
     converse.user.status.message.set('In a meeting');
     converse.user.status.message.set('In a meeting');
 
 
@@ -344,7 +477,7 @@ Provide the JID of the contact you want to add:
     .. code-block:: javascript
     .. code-block:: javascript
 
 
     converse.contacts.add('buddy@example.com')
     converse.contacts.add('buddy@example.com')
-    
+
 You may also provide the fullname. If not present, we use the jid as fullname:
 You may also provide the fullname. If not present, we use the jid as fullname:
 
 
     .. code-block:: javascript
     .. code-block:: javascript
@@ -663,7 +796,7 @@ An example plugin
     }(this, function ($, strophe, utils, converse_api) {
     }(this, function ($, strophe, utils, converse_api) {
 
 
         // Wrap your UI strings with the __ function for translation support.
         // Wrap your UI strings with the __ function for translation support.
-        var __ = $.proxy(utils.__, this); 
+        var __ = $.proxy(utils.__, this);
 
 
         // Strophe methods for building stanzas
         // Strophe methods for building stanzas
         var Strophe = strophe.Strophe;
         var Strophe = strophe.Strophe;

+ 29 - 0
spec/mam.js

@@ -227,6 +227,35 @@
                 Date.prototype.getTimezoneOffset = getTimezoneOffset;
                 Date.prototype.getTimezoneOffset = getTimezoneOffset;
            });
            });
 
 
+           it("accepts \"before\" with an empty string as value to reverse the order", function () {
+                var sent_stanza, IQ_id;
+                var sendIQ = converse.connection.sendIQ;
+                spyOn(converse.connection, 'sendIQ').andCallFake(function (iq, callback, errback) {
+                    sent_stanza = iq;
+                    IQ_id = sendIQ.bind(this)(iq, callback, errback);
+                });
+                if (!converse.features.findWhere({'var': Strophe.NS.MAM})) {
+                    converse.features.create({'var': Strophe.NS.MAM});
+                }
+                converse_api.archive.query({'before': '', 'max':10});
+                var queryid = $(sent_stanza.toString()).find('query').attr('queryid');
+                expect(sent_stanza.toString()).toBe(
+                    "<iq type='set' xmlns='jabber:client' id='"+IQ_id+"'>"+
+                        "<query xmlns='urn:xmpp:mam:0' queryid='"+queryid+"'>"+
+                            "<x xmlns='jabber:x:data'>"+
+                                "<field var='FORM_TYPE'>"+
+                                    "<value>urn:xmpp:mam:0</value>"+
+                                "</field>"+
+                            "</x>"+
+                            "<set xmlns='http://jabber.org/protocol/rsm'>"+
+                                "<max>10</max>"+
+                                "<before></before>"+
+                            "</set>"+
+                        "</query>"+
+                    "</iq>"
+                );
+           });
+
         }, converse, mock, test_utils));
         }, converse, mock, test_utils));
 
 
         describe("The default preference", $.proxy(function (mock, test_utils) {
         describe("The default preference", $.proxy(function (mock, test_utils) {