src/client.js
/**
 * Construct a Matrix Client. Only directly construct this if you want to use
 * custom modules. Normally, {@link createClient} should be used
 * as it specifies 'sensible' defaults for these modules.
 * @constructor
 * @extends {external:EventEmitter}
 * @extends {module:base-apis~MatrixBaseApis}
 *
 * @param {Object} opts The configuration options for this client.
 * @param {string} opts.baseUrl Required. The base URL to the client-server
 * HTTP API.
 * @param {string} opts.idBaseUrl Optional. The base identity server URL for
 * identity server requests.
 * @param {Function} opts.request Required. The function to invoke for HTTP
 * requests. The value of this property is typically <code>require("request")
 * </code> as it returns a function which meets the required interface. See
 * {@link requestFunction} for more information.
 *
 * @param {string} opts.accessToken The access_token for this user.
 *
 * @param {string} opts.userId The user ID for this user.
 *
 * @param {Object=} opts.store
 *    The data store used for sync data from the homeserver. If not specified,
 *    this client will not store any HTTP responses. The `createClient` helper
 *    will create a default store if needed.
 *
 * @param {module:store/session/webstorage~WebStorageSessionStore} opts.sessionStore
 *    A store to be used for end-to-end crypto session data. Most data has been
 *    migrated out of here to `cryptoStore` instead. If not specified,
 *    end-to-end crypto will be disabled. The `createClient` helper
 *    _will not_ create this store at the moment.
 *
 * @param {module:crypto.store.base~CryptoStore} opts.cryptoStore
 *    A store to be used for end-to-end crypto session data. If not specified,
 *    end-to-end crypto will be disabled. The `createClient` helper will create
 *    a default store if needed.
 *
 * @param {string=} opts.deviceId A unique identifier for this device; used for
 *    tracking things like crypto keys and access tokens.  If not specified,
 *    end-to-end crypto will be disabled.
 *
 * @param {Object} opts.scheduler Optional. The scheduler to use. If not
 * specified, this client will not retry requests on failure. This client
 * will supply its own processing function to
 * {@link module:scheduler~MatrixScheduler#setProcessFunction}.
 *
 * @param {Object} opts.queryParams Optional. Extra query parameters to append
 * to all requests with this client. Useful for application services which require
 * <code>?user_id=</code>.
 *
 * @param {Number=} opts.localTimeoutMs Optional. The default maximum amount of
 * time to wait before timing out HTTP requests. If not specified, there is no timeout.
 *
 * @param {boolean} [opts.useAuthorizationHeader = false] Set to true to use
 * Authorization header instead of query param to send the access token to the server.
 *
 * @param {boolean} [opts.timelineSupport = false] Set to true to enable
 * improved timeline support ({@link
 * module:client~MatrixClient#getEventTimeline getEventTimeline}). It is
 * disabled by default for compatibility with older clients - in particular to
 * maintain support for back-paginating the live timeline after a '/sync'
 * result with a gap.
 *
 * @param {boolean} [opts.unstableClientRelationAggregation = false]
 * Optional. Set to true to enable client-side aggregation of event relations
 * via `EventTimelineSet#getRelationsForEvent`.
 * This feature is currently unstable and the API may change without notice.
 *
 * @param {Array} [opts.verificationMethods] Optional. The verification method
 * that the application can handle.  Each element should be an item from {@link
 * module:crypto~verificationMethods verificationMethods}, or a class that
 * implements the {$link module:crypto/verification/Base verifier interface}.
 */
Construct a Matrix Client. Only directly construct this if you want to use
custom modules. Normally,  createClient should be used
as it specifies 'sensible' defaults for these modules.

@param {Object} opts The configuration options for this client.

@param {string} opts.accessToken The access_token for this user.

@param {string} opts.userId The user ID for this user.

@param {Object=} opts.store
The data store used for sync data from the homeserver. If not specified,
this client will not store any HTTP responses. The `createClient` helper
will create a default store if needed.

@param {module:store/session/webstorage~WebStorageSessionStore} opts.sessionStore
A store to be used for end-to-end crypto session data. Most data has been
migrated out of here to `cryptoStore` instead. If not specified,
end-to-end crypto will be disabled. The `createClient` helper
_will not_ create this store at the moment.

@param {module:crypto.store.base~CryptoStore} opts.cryptoStore
A store to be used for end-to-end crypto session data. If not specified,
end-to-end crypto will be disabled. The `createClient` helper will create
a default store if needed.

@param {string=} opts.deviceId A unique identifier for this device; used for
tracking things like crypto keys and access tokens.  If not specified,
end-to-end crypto will be disabled.







@param {boolean} [opts.useAuthorizationHeader = false] Set to true to use
Authorization header instead of query param to send the access token to the server.

@param {boolean} [opts.timelineSupport = false] Set to true to enable
improved timeline support ({@link
module:client~MatrixClient#getEventTimeline getEventTimeline}). It is
disabled by default for compatibility with older clients - in particular to
maintain support for back-paginating the live timeline after a '/sync'
result with a gap.

@param {boolean} [opts.unstableClientRelationAggregation = false]
Optional. Set to true to enable client-side aggregation of event relations
via `EventTimelineSet#getRelationsForEvent`.
This feature is currently unstable and the API may change without notice.


Construct a Matrix Client . Only directly construct this if you want to use custom modules . Normally createClient should be used as it specifies ' sensible ' defaults for these modules . @param { Object } opts The configuration options for this client . @param { string } opts . accessToken The access_token for this user . @param { string } opts . userId The user ID for this user . @param { Object = } opts . store The data store used for sync data from the homeserver . If not specified this client will not store any HTTP responses . The ` createClient ` helper will create a default store if needed . @param { module : store / session / webstorage~WebStorageSessionStore } opts . sessionStore A store to be used for end - to - end crypto session data . Most data has been migrated out of here to ` cryptoStore ` instead . If not specified end - to - end crypto will be disabled . The ` createClient ` helper _will not_ create this store at the moment . @param { module : crypto . store . base~CryptoStore } opts . cryptoStore A store to be used for end - to - end crypto session data . If not specified end - to - end crypto will be disabled . The ` createClient ` helper will create a default store if needed . @param { string = } opts . deviceId A unique identifier for this device ; used for tracking things like crypto keys and access tokens . If not specified end - to - end crypto will be disabled . @param { boolean } [ opts . useAuthorizationHeader = false ] Set to true to use Authorization header instead of query param to send the access token to the server . @param { boolean } [ opts . timelineSupport = false ] Set to true to enable improved timeline support ( { @link module : client~MatrixClient#getEventTimeline getEventTimeline } ) . It is disabled by default for compatibility with older clients - in particular to maintain support for back - paginating the live timeline after a ' / sync ' result with a gap . @param { boolean } [ opts . unstableClientRelationAggregation = false ] Optional . Set to true to enable client - side aggregation of event relations via ` EventTimelineSet#getRelationsForEvent ` . This feature is currently unstable and the API may change without notice .
function MatrixClient(opts) {
    if (opts.baseUrl && opts.baseUrl.endsWith("/")) {
        opts.baseUrl = opts.baseUrl.substr(0, opts.baseUrl.length - 1);
    }
    if (opts.idBaseUrl && opts.idBaseUrl.endsWith("/")) {
        opts.idBaseUrl = opts.idBaseUrl.substr(0, opts.idBaseUrl.length - 1);
    }
    MatrixBaseApis.call(this, opts);
    this.olmVersion = null; 
    this.reEmitter = new ReEmitter(this);
    this.store = opts.store || new StubStore();
    this.deviceId = opts.deviceId || null;
    const userId = (opts.userId || null);
    this.credentials = {
        userId: userId,
    };
    this.scheduler = opts.scheduler;
    if (this.scheduler) {
        const self = this;
        this.scheduler.setProcessFunction(function(eventToSend) {
            const room = self.getRoom(eventToSend.getRoomId());
            if (eventToSend.status !== EventStatus.SENDING) {
                _updatePendingEventStatus(room, eventToSend,
                                          EventStatus.SENDING);
            }
            return _sendEventHttpRequest(self, eventToSend);
        });
    }
    this.clientRunning = false;
    this.callList = {
    };
    const call = webRtcCall.createNewMatrixCall(this);
    this._supportsVoip = false;
    if (call) {
        setupCallEventHandler(this);
        this._supportsVoip = true;
    }
    this._syncingRetry = null;
    this._syncApi = null;
    this._peekSync = null;
    this._isGuest = false;
    this._ongoingScrollbacks = {};
    this.timelineSupport = Boolean(opts.timelineSupport);
    this.urlPreviewCache = {};
    this._notifTimelineSet = null;
    this.unstableClientRelationAggregation = !!opts.unstableClientRelationAggregation;
    this._crypto = null;
    this._cryptoStore = opts.cryptoStore;
    this._sessionStore = opts.sessionStore;
    this._verificationMethods = opts.verificationMethods;
    this._forceTURN = opts.forceTURN || false;
    this._roomList = new RoomList(this._cryptoStore);
    this._pushProcessor = new PushProcessor(this);
    this._serverSupportsLazyLoading = null;
    this._cachedCapabilities = null; 
    this.on("Event.decrypted", (event) => {
        const oldActions = event.getPushActions();
        const actions = this._pushProcessor.actionsForEvent(event);
        event.setPushActions(actions); 
        const room = this.getRoom(event.getRoomId());
        if (!room) return;
        const currentCount = room.getUnreadNotificationCount("highlight");
        const oldHighlight = oldActions && oldActions.tweaks
            ? !!oldActions.tweaks.highlight : false;
        const newHighlight = actions && actions.tweaks
            ? !!actions.tweaks.highlight : false;
        if (oldHighlight !== newHighlight || currentCount > 0) {
            if (!room.hasUserReadEvent(this.getUserId(), event.getId())) {
                let newCount = currentCount;
                if (newHighlight && !oldHighlight) newCount++;
                if (!newHighlight && oldHighlight) newCount--;
                room.setUnreadNotificationCount("highlight", newCount);
                const totalCount = room.getUnreadNotificationCount('total');
                if (totalCount < newCount) {
                    room.setUnreadNotificationCount('total', newCount);
                }
            }
        }
    });
}
function MatrixClient ( opts ) { if ( opts . baseUrl && opts . baseUrl . endsWith ( "/" ) ) { opts . baseUrl = opts . baseUrl . substr ( 0 , opts . baseUrl . length - 1 ) ; } if ( opts . idBaseUrl && opts . idBaseUrl . endsWith ( "/" ) ) { opts . idBaseUrl = opts . idBaseUrl . substr ( 0 , opts . idBaseUrl . length - 1 ) ; } MatrixBaseApis . call ( this , opts ) ; this . olmVersion = null ; this . reEmitter = new ReEmitter ( this ) ; this . store = opts . store || new StubStore ( ) ; this . deviceId = opts . deviceId || null ; const userId = ( opts . userId || null ) ; this . credentials = { userId : userId , } ; this . scheduler = opts . scheduler ; if ( this . scheduler ) { const self = this ; this . scheduler . setProcessFunction ( function ( eventToSend ) { const room = self . getRoom ( eventToSend . getRoomId ( ) ) ; if ( eventToSend . status !== EventStatus . SENDING ) { _updatePendingEventStatus ( room , eventToSend , EventStatus . SENDING ) ; } return _sendEventHttpRequest ( self , eventToSend ) ; } ) ; } this . clientRunning = false ; this . callList = { } ; const call = webRtcCall . createNewMatrixCall ( this ) ; this . _supportsVoip = false ; if ( call ) { setupCallEventHandler ( this ) ; this . _supportsVoip = true ; } this . _syncingRetry = null ; this . _syncApi = null ; this . _peekSync = null ; this . _isGuest = false ; this . _ongoingScrollbacks = { } ; this . timelineSupport = Boolean ( opts . timelineSupport ) ; this . urlPreviewCache = { } ; this . _notifTimelineSet = null ; this . unstableClientRelationAggregation = ! ! opts . unstableClientRelationAggregation ; this . _crypto = null ; this . _cryptoStore = opts . cryptoStore ; this . _sessionStore = opts . sessionStore ; this . _verificationMethods = opts . verificationMethods ; this . _forceTURN = opts . forceTURN || false ; this . _roomList = new RoomList ( this . _cryptoStore ) ; this . _pushProcessor = new PushProcessor ( this ) ; this . _serverSupportsLazyLoading = null ; this . _cachedCapabilities = null ; this . on ( "Event.decrypted" , ( event ) => { const oldActions = event . getPushActions ( ) ; const actions = this . _pushProcessor . actionsForEvent ( event ) ; event . setPushActions ( actions ) ; const room = this . getRoom ( event . getRoomId ( ) ) ; if ( ! room ) return ; const currentCount = room . getUnreadNotificationCount ( "highlight" ) ; const oldHighlight = oldActions && oldActions . tweaks ? ! ! oldActions . tweaks . highlight : false ; const newHighlight = actions && actions . tweaks ? ! ! actions . tweaks . highlight : false ; if ( oldHighlight !== newHighlight || currentCount > 0 ) { if ( ! room . hasUserReadEvent ( this . getUserId ( ) , event . getId ( ) ) ) { let newCount = currentCount ; if ( newHighlight && ! oldHighlight ) newCount ++ ; if ( ! newHighlight && oldHighlight ) newCount -- ; room . setUnreadNotificationCount ( "highlight" , newCount ) ; const totalCount = room . getUnreadNotificationCount ( 'total' ) ; if ( totalCount < newCount ) { room . setUnreadNotificationCount ( 'total' , newCount ) ; } } } } ) ; }
Construct a Matrix Client.
Construct a Matrix Client .
// Allow trailing slash in HS url // Allow trailing slash in IS url // Populated after initCrypto is done // callId: MatrixCall // try constructing a MatrixCall to see if we are running in an environment // which has WebRTC. If we are, listen for and handle m.call.* events. // List of which rooms have encryption enabled: separate from crypto because // we still want to know which rooms are encrypted even if crypto is disabled: // we don't want to start sending unencrypted events to them. // The pushprocessor caches useful things, so keep one and re-use it // { capabilities: {}, lastUpdated: timestamp } // The SDK doesn't really provide a clean way for events to recalculate the push // actions for themselves, so we have to kinda help them out when they are encrypted. // We do this so that push rules are correctly executed on events in their decrypted // state, such as highlights when the user's name is mentioned. // Might as well while we're here // Ensure the unread counts are kept up to date if the event is encrypted // We also want to make sure that the notification count goes up if we already // have encrypted events to avoid other code from resetting 'highlight' to zero. // TODO: Handle mentions received while the client is offline // See also https://github.com/vector-im/riot-web/issues/9069 // Fix 'Mentions Only' rooms from not having the right badge count