index : matrix-js-sdk

My fork of matrix-js-sdk

path: root/README.md
blob: c252447c4ff96ba243c211948e19a5dd2c381217 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
Matrix Javascript SDK
=====================

This is the [Matrix](https://matrix.org) Client-Server r0 SDK for
JavaScript. This SDK can be run in a browser or in Node.js.

Quickstart
==========

In a browser
------------
Download the browser version from
https://github.com/matrix-org/matrix-js-sdk/releases/latest and add that as a
``<script>`` to your page. There will be a global variable ``matrixcs``
attached to ``window`` through which you can access the SDK. See below for how to
include libolm to enable end-to-end-encryption.

The browser bundle supports recent versions of browsers. Typically this is ES2015
or `> 0.5%, last 2 versions, Firefox ESR, not dead` if using 
[browserlists](https://github.com/browserslist/browserslist).

Please check [the working browser example](examples/browser) for more information.

In Node.js
----------

Ensure you have the latest LTS version of Node.js installed.

This SDK targets Node 10 for compatibility, which translates to ES6. If you're using
a bundler like webpack you'll likely have to transpile dependencies, including this
SDK, to match your target browsers.

Using `yarn` instead of `npm` is recommended. Please see the Yarn [install guide](https://yarnpkg.com/docs/install/) 
if you do not have it already.

``yarn add matrix-js-sdk``

```javascript
  import * as sdk from "matrix-js-sdk";
  const client = sdk.createClient("https://matrix.org");
  client.publicRooms(function(err, data) {
    console.log("Public Rooms: %s", JSON.stringify(data));
  });
```

See below for how to include libolm to enable end-to-end-encryption. Please check
[the Node.js terminal app](examples/node) for a more complex example.

To start the client:

```javascript
await client.startClient({initialSyncLimit: 10});
```

You can perform a call to `/sync` to get the current state of the client:

```javascript
client.once('sync', function(state, prevState, res) {
    if(state === 'PREPARED') {
        console.log("prepared");
    } else {
        console.log(state);
        process.exit(1);
    }
});
```

To send a message:

```javascript
const content = {
    "body": "message text",
    "msgtype": "m.text"
};
client.sendEvent("roomId", "m.room.message", content, "", (err, res) => {
    console.log(err);
});
```

To listen for message events:

```javascript
client.on("Room.timeline", function(event, room, toStartOfTimeline) {
  if (event.getType() !== "m.room.message") {
    return; // only use messages
  }
  console.log(event.event.content.body);
});
```

By default, the `matrix-js-sdk` client uses the `MemoryStore` to store events as they are received. For example to iterate through the currently stored timeline for a room:

```javascript
Object.keys(client.store.rooms).forEach((roomId) => {
  client.getRoom(roomId).timeline.forEach(t => {
      console.log(t.event);
  });
});
```

What does this SDK do?
----------------------

This SDK provides a full object model around the Matrix Client-Server API and emits
events for incoming data and state changes. Aside from wrapping the HTTP API, it:
 - Handles syncing (via `/initialSync` and `/events`)
 - Handles the generation of "friendly" room and member names.
 - Handles historical `RoomMember` information (e.g. display names).
 - Manages room member state across multiple events (e.g. it handles typing, power
   levels and membership changes).
 - Exposes high-level objects like `Rooms`, `RoomState`, `RoomMembers` and `Users`
   which can be listened to for things like name changes, new messages, membership
   changes, presence changes, and more.
 - Handle "local echo" of messages sent using the SDK. This means that messages
   that have just been sent will appear in the timeline as 'sending', until it
   completes. This is beneficial because it prevents there being a gap between
   hitting the send button and having the "remote echo" arrive.
 - Mark messages which failed to send as not sent.
 - Automatically retry requests to send messages due to network errors.
 - Automatically retry requests to send messages due to rate limiting errors.
 - Handle queueing of messages.
 - Handles pagination.
 - Handle assigning push actions for events.
 - Handles room initial sync on accepting invites.
 - Handles WebRTC calling.

Later versions of the SDK will:
 - Expose a `RoomSummary` which would be suitable for a recents page.
 - Provide different pluggable storage layers (e.g. local storage, database-backed)

Usage
=====


Conventions
-----------

### Emitted events

The SDK will emit events using an ``EventEmitter``. It also
emits object models (e.g. ``Rooms``, ``RoomMembers``) when they
are updated.

```javascript
  // Listen for low-level MatrixEvents
  client.on("event", function(event) {
    console.log(event.getType());
  });

  // Listen for typing changes
  client.on("RoomMember.typing", function(event, member) {
    if (member.typing) {
      console.log(member.name + " is typing...");
    }
    else {
      console.log(member.name + " stopped typing.");
    }
  });

  // start the client to setup the connection to the server
  client.startClient();
```

### Promises and Callbacks

Most of the methods in the SDK are asynchronous: they do not directly return a
result, but instead return a [Promise](http://documentup.com/kriskowal/q/)
which will be fulfilled in the future.

The typical usage is something like:

```javascript
  matrixClient.someMethod(arg1, arg2).then(function(result) {
    ...
  });
```

Alternatively, if you have a Node.js-style ``callback(err, result)`` function,
you can pass the result of the promise into it with something like:

```javascript
  matrixClient.someMethod(arg1, arg2).nodeify(callback);
```

The main thing to note is that it is an error to discard the result of a
promise-returning function, as that will cause exceptions to go unobserved. If
you have nothing better to do with the result, just call ``.done()`` on it. See
http://documentup.com/kriskowal/q/#the-end for more information.

Methods which return a promise show this in their documentation.

Many methods in the SDK support *both* Node.js-style callbacks *and* Promises,
via an optional ``callback`` argument. The callback support is now deprecated:
new methods do not include a ``callback`` argument, and in the future it may be
removed from existing methods.

Examples
--------
This section provides some useful code snippets which demonstrate the
core functionality of the SDK. These examples assume the SDK is setup like this:

```javascript
   import * as sdk from "matrix-js-sdk";
   const myUserId = "@example:localhost";
   const myAccessToken = "QGV4YW1wbGU6bG9jYWxob3N0.qPEvLuYfNBjxikiCjP";
   const matrixClient = sdk.createClient({
       baseUrl: "http://localhost:8008",
       accessToken: myAccessToken,
       userId: myUserId
   });
```

### Automatically join rooms when invited

```javascript
   matrixClient.on("RoomMember.membership", function(event, member) {
       if (member.membership === "invite" && member.userId === myUserId) {
           matrixClient.joinRoom(member.roomId).then(function() {
               console.log("Auto-joined %s", member.roomId);
           });
       }
   });

   matrixClient.startClient();
```

### Print out messages for all rooms

```javascript
   matrixClient.on("Room.timeline", function(event, room, toStartOfTimeline) {
       if (toStartOfTimeline) {
           return; // don't print paginated results
       }
       if (event.getType() !== "m.room.message") {
           return; // only print messages
       }
       console.log(
           // the room name will update with m.room.name events automatically
           "(%s) %s :: %s", room.name, event.getSender(), event.getContent().body
       );
   });

   matrixClient.startClient();
```

Output:
```
  (My Room) @megan:localhost :: Hello world
  (My Room) @megan:localhost :: how are you?
  (My Room) @example:localhost :: I am good
  (My Room) @example:localhost :: change the room name
  (My New Room) @megan:localhost :: done
```

### Print out membership lists whenever they are changed

```javascript
   matrixClient.on("RoomState.members", function(event, state, member) {
       const room = matrixClient.getRoom(state.roomId);
       if (!room) {
           return;
       }
       const memberList = state.getMembers();
       console.log(room.name);
       console.log(Array(room.name.length + 1).join("="));  // underline
       for (var i = 0; i < memberList.length; i++) {
           console.log(
               "(%s) %s",
               memberList[i].membership,
               memberList[i].name
           );
       }
   });

   matrixClient.startClient();
```

Output:
```
  My Room
  =======
  (join) @example:localhost
  (leave) @alice:localhost
  (join) Bob
  (invite) @charlie:localhost
```

API Reference
=============

A hosted reference can be found at
http://matrix-org.github.io/matrix-js-sdk/index.html

This SDK uses JSDoc3 style comments. You can manually build and
host the API reference from the source files like this:

```
  $ yarn gendoc
  $ cd .jsdoc
  $ python -m SimpleHTTPServer 8005
```

Then visit ``http://localhost:8005`` to see the API docs.

End-to-end encryption support
=============================

The SDK supports end-to-end encryption via the Olm and Megolm protocols, using
[libolm](https://gitlab.matrix.org/matrix-org/olm). It is left up to the
application to make libolm available, via the ``Olm`` global.

It is also necessry to call ``matrixClient.initCrypto()`` after creating a new
``MatrixClient`` (but **before** calling ``matrixClient.startClient()``) to
initialise the crypto layer.

If the ``Olm`` global is not available, the SDK will show a warning, as shown
below; ``initCrypto()`` will also fail.

```
Unable to load crypto module: crypto will be disabled: Error: global.Olm is not defined
```

If the crypto layer is not (successfully) initialised, the SDK will continue to
work for unencrypted rooms, but it will not support the E2E parts of the Matrix
specification.

To provide the Olm library in a browser application:

 * download the transpiled libolm (from https://packages.matrix.org/npm/olm/).
 * load ``olm.js`` as a ``<script>`` *before* ``browser-matrix.js``.

To provide the Olm library in a node.js application:

 * ``yarn add https://packages.matrix.org/npm/olm/olm-3.1.4.tgz``
   (replace the URL with the latest version you want to use from
    https://packages.matrix.org/npm/olm/)
 * ``global.Olm = require('olm');`` *before* loading ``matrix-js-sdk``.

If you want to package Olm as dependency for your node.js application, you can
use ``yarn add https://packages.matrix.org/npm/olm/olm-3.1.4.tgz``. If your
application also works without e2e crypto enabled, add ``--optional`` to mark it
as an optional dependency.


Contributing
============
*This section is for people who want to modify the SDK. If you just
want to use this SDK, skip this section.*

First, you need to pull in the right build tools:
```
 $ yarn install
```

Building
--------

To build a browser version from scratch when developing::
```
 $ yarn build
```

To run tests (Jasmine)::
```
 $ yarn test
```

To run linting:
```
 $ yarn lint
```