@@ -17,10 +17,19 @@ limitations under the License.
1717import SdkConfig from '../SdkConfig' ;
1818import sdk from "../index" ;
1919import Modal from '../Modal' ;
20- import { IntegrationManagerInstance , KIND_ACCOUNT , KIND_CONFIG } from "./IntegrationManagerInstance" ;
20+ import { IntegrationManagerInstance , KIND_ACCOUNT , KIND_CONFIG , KIND_HOMESERVER } from "./IntegrationManagerInstance" ;
2121import type { MatrixClient , MatrixEvent } from "matrix-js-sdk" ;
2222import WidgetUtils from "../utils/WidgetUtils" ;
2323import MatrixClientPeg from "../MatrixClientPeg" ;
24+ import { AutoDiscovery } from "matrix-js-sdk" ;
25+
26+ const HS_MANAGERS_REFRESH_INTERVAL = 8 * 60 * 60 * 1000 ; // 8 hours
27+ const KIND_PREFERENCE = [
28+ // Ordered: first is most preferred, last is least preferred.
29+ KIND_ACCOUNT ,
30+ KIND_HOMESERVER ,
31+ KIND_CONFIG ,
32+ ] ;
2433
2534export class IntegrationManagers {
2635 static _instance ;
@@ -34,6 +43,8 @@ export class IntegrationManagers {
3443
3544 _managers : IntegrationManagerInstance [ ] = [ ] ;
3645 _client : MatrixClient ;
46+ _wellknownRefreshTimerId : number = null ;
47+ _primaryManager : IntegrationManagerInstance ;
3748
3849 constructor ( ) {
3950 this . _compileManagers ( ) ;
@@ -44,16 +55,19 @@ export class IntegrationManagers {
4455 this . _client = MatrixClientPeg . get ( ) ;
4556 this . _client . on ( "accountData" , this . _onAccountData . bind ( this ) ) ;
4657 this . _compileManagers ( ) ;
58+ setInterval ( ( ) => this . _setupHomeserverManagers ( ) , HS_MANAGERS_REFRESH_INTERVAL ) ;
4759 }
4860
4961 stopWatching ( ) : void {
5062 if ( ! this . _client ) return ;
5163 this . _client . removeListener ( "accountData" , this . _onAccountData . bind ( this ) ) ;
64+ if ( this . _wellknownRefreshTimerId !== null ) clearInterval ( this . _wellknownRefreshTimerId ) ;
5265 }
5366
5467 _compileManagers ( ) {
5568 this . _managers = [ ] ;
5669 this . _setupConfiguredManager ( ) ;
70+ this . _setupHomeserverManagers ( ) ;
5771 this . _setupAccountManagers ( ) ;
5872 }
5973
@@ -63,6 +77,42 @@ export class IntegrationManagers {
6377
6478 if ( apiUrl && uiUrl ) {
6579 this . _managers . push ( new IntegrationManagerInstance ( KIND_CONFIG , apiUrl , uiUrl ) ) ;
80+ this . _primaryManager = null ; // reset primary
81+ }
82+ }
83+
84+ async _setupHomeserverManagers ( ) {
85+ try {
86+ console . log ( "Updating homeserver-configured integration managers..." ) ;
87+ const homeserverDomain = MatrixClientPeg . getHomeserverName ( ) ;
88+ const discoveryResponse = await AutoDiscovery . getRawClientConfig ( homeserverDomain ) ;
89+ if ( discoveryResponse && discoveryResponse [ 'm.integrations' ] ) {
90+ let managers = discoveryResponse [ 'm.integrations' ] [ 'managers' ] ;
91+ if ( ! Array . isArray ( managers ) ) managers = [ ] ; // make it an array so we can wipe the HS managers
92+
93+ console . log ( `Homeserver has ${ managers . length } integration managers` ) ;
94+
95+ // Clear out any known managers for the homeserver
96+ // TODO: Log out of the scalar clients
97+ this . _managers = this . _managers . filter ( m => m . kind !== KIND_HOMESERVER ) ;
98+
99+ // Now add all the managers the homeserver wants us to have
100+ for ( const hsManager of managers ) {
101+ if ( ! hsManager [ "api_url" ] ) continue ;
102+ this . _managers . push ( new IntegrationManagerInstance (
103+ KIND_HOMESERVER ,
104+ hsManager [ "api_url" ] ,
105+ hsManager [ "ui_url" ] , // optional
106+ ) ) ;
107+ }
108+
109+ this . _primaryManager = null ; // reset primary
110+ } else {
111+ console . log ( "Homeserver has no integration managers" ) ;
112+ }
113+ } catch ( e ) {
114+ console . error ( e ) ;
115+ // Errors during discovery are non-fatal
66116 }
67117 }
68118
@@ -77,8 +127,11 @@ export class IntegrationManagers {
77127 const apiUrl = data [ 'api_url' ] ;
78128 if ( ! apiUrl || ! uiUrl ) return ;
79129
80- this . _managers . push ( new IntegrationManagerInstance ( KIND_ACCOUNT , apiUrl , uiUrl ) ) ;
130+ const manager = new IntegrationManagerInstance ( KIND_ACCOUNT , apiUrl , uiUrl ) ;
131+ manager . id = w [ 'id' ] || w [ 'state_key' ] || '' ;
132+ this . _managers . push ( manager ) ;
81133 } ) ;
134+ this . _primaryManager = null ; // reset primary
82135 }
83136
84137 _onAccountData ( ev : MatrixEvent ) : void {
@@ -91,9 +144,28 @@ export class IntegrationManagers {
91144 return this . _managers . length > 0 ;
92145 }
93146
147+ getOrderedManagers ( ) : IntegrationManagerInstance [ ] {
148+ const ordered = [ ] ;
149+ for ( const kind of KIND_PREFERENCE ) {
150+ const managers = this . _managers . filter ( m => m . kind === kind ) ;
151+ if ( ! managers || ! managers . length ) continue ;
152+
153+ if ( kind === KIND_ACCOUNT ) {
154+ // Order by state_keys (IDs)
155+ managers . sort ( ( a , b ) => a . id . localeCompare ( b . id ) ) ;
156+ }
157+
158+ ordered . push ( ...managers ) ;
159+ }
160+ return ordered ;
161+ }
162+
94163 getPrimaryManager ( ) : IntegrationManagerInstance {
95164 if ( this . hasManager ( ) ) {
96- return this . _managers [ this . _managers . length - 1 ] ;
165+ if ( this . _primaryManager ) return this . _primaryManager ;
166+
167+ this . _primaryManager = this . getOrderedManagers ( ) [ 0 ] ;
168+ return this . _primaryManager ;
97169 } else {
98170 return null ;
99171 }
0 commit comments