@@ -17,10 +17,19 @@ limitations under the License.
17
17
import SdkConfig from '../SdkConfig' ;
18
18
import sdk from "../index" ;
19
19
import Modal from '../Modal' ;
20
- import { IntegrationManagerInstance , KIND_ACCOUNT , KIND_CONFIG } from "./IntegrationManagerInstance" ;
20
+ import { IntegrationManagerInstance , KIND_ACCOUNT , KIND_CONFIG , KIND_HOMESERVER } from "./IntegrationManagerInstance" ;
21
21
import type { MatrixClient , MatrixEvent } from "matrix-js-sdk" ;
22
22
import WidgetUtils from "../utils/WidgetUtils" ;
23
23
import 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
+ ] ;
24
33
25
34
export class IntegrationManagers {
26
35
static _instance ;
@@ -34,6 +43,8 @@ export class IntegrationManagers {
34
43
35
44
_managers : IntegrationManagerInstance [ ] = [ ] ;
36
45
_client : MatrixClient ;
46
+ _wellknownRefreshTimerId : number = null ;
47
+ _primaryManager : IntegrationManagerInstance ;
37
48
38
49
constructor ( ) {
39
50
this . _compileManagers ( ) ;
@@ -44,16 +55,19 @@ export class IntegrationManagers {
44
55
this . _client = MatrixClientPeg . get ( ) ;
45
56
this . _client . on ( "accountData" , this . _onAccountData . bind ( this ) ) ;
46
57
this . _compileManagers ( ) ;
58
+ setInterval ( ( ) => this . _setupHomeserverManagers ( ) , HS_MANAGERS_REFRESH_INTERVAL ) ;
47
59
}
48
60
49
61
stopWatching ( ) : void {
50
62
if ( ! this . _client ) return ;
51
63
this . _client . removeListener ( "accountData" , this . _onAccountData . bind ( this ) ) ;
64
+ if ( this . _wellknownRefreshTimerId !== null ) clearInterval ( this . _wellknownRefreshTimerId ) ;
52
65
}
53
66
54
67
_compileManagers ( ) {
55
68
this . _managers = [ ] ;
56
69
this . _setupConfiguredManager ( ) ;
70
+ this . _setupHomeserverManagers ( ) ;
57
71
this . _setupAccountManagers ( ) ;
58
72
}
59
73
@@ -63,6 +77,42 @@ export class IntegrationManagers {
63
77
64
78
if ( apiUrl && uiUrl ) {
65
79
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
66
116
}
67
117
}
68
118
@@ -77,8 +127,11 @@ export class IntegrationManagers {
77
127
const apiUrl = data [ 'api_url' ] ;
78
128
if ( ! apiUrl || ! uiUrl ) return ;
79
129
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 ) ;
81
133
} ) ;
134
+ this . _primaryManager = null ; // reset primary
82
135
}
83
136
84
137
_onAccountData ( ev : MatrixEvent ) : void {
@@ -93,7 +146,20 @@ export class IntegrationManagers {
93
146
94
147
getPrimaryManager ( ) : IntegrationManagerInstance {
95
148
if ( this . hasManager ( ) ) {
96
- return this . _managers [ this . _managers . length - 1 ] ;
149
+ if ( this . _primaryManager ) return this . _primaryManager ;
150
+
151
+ for ( const kind of KIND_PREFERENCE ) {
152
+ const managers = this . _managers . filter ( m => m . kind === kind ) ;
153
+ if ( ! managers || ! managers . length ) continue ;
154
+
155
+ if ( kind === KIND_ACCOUNT ) {
156
+ // Order by state_keys (IDs)
157
+ managers . sort ( ( a , b ) => a . id . localeCompare ( b . id ) ) ;
158
+ }
159
+
160
+ this . _primaryManager = managers [ 0 ] ;
161
+ return this . _primaryManager ;
162
+ }
97
163
} else {
98
164
return null ;
99
165
}
0 commit comments