11/*
2- * Copyright 2020 The Matrix.org Foundation C.I.C.
2+ * Copyright 2020 - 2021 The Matrix.org Foundation C.I.C.
33 *
44 * Licensed under the Apache License, Version 2.0 (the "License");
55 * you may not use this file except in compliance with the License.
@@ -23,6 +23,7 @@ import {
2323 MatrixCapabilities ,
2424 OpenIDRequestState ,
2525 SimpleObservable ,
26+ Symbols ,
2627 Widget ,
2728 WidgetDriver ,
2829 WidgetEventCapability ,
@@ -44,7 +45,8 @@ import { CHAT_EFFECTS } from "../../effects";
4445import { containsEmoji } from "../../effects/utils" ;
4546import dis from "../../dispatcher/dispatcher" ;
4647import { tryTransformPermalinkToLocalHref } from "../../utils/permalinks/Permalinks" ;
47- import { MatrixEvent } from "matrix-js-sdk/src/models/event" ;
48+ import { IEvent , MatrixEvent } from "matrix-js-sdk/src/models/event" ;
49+ import { Room } from "matrix-js-sdk" ;
4850
4951// TODO: Purge this from the universe
5052
@@ -119,9 +121,9 @@ export class StopGapWidgetDriver extends WidgetDriver {
119121 return new Set ( iterableUnion ( allowedSoFar , requested ) ) ;
120122 }
121123
122- public async sendEvent ( eventType : string , content : any , stateKey : string = null ) : Promise < ISendEventDetails > {
124+ public async sendEvent ( eventType : string , content : any , stateKey : string = null , targetRoomId : string = null ) : Promise < ISendEventDetails > {
123125 const client = MatrixClientPeg . get ( ) ;
124- const roomId = ActiveRoomObserver . activeRoomId ;
126+ const roomId = targetRoomId || ActiveRoomObserver . activeRoomId ;
125127
126128 if ( ! client || ! roomId ) throw new Error ( "Not in a room or not attached to a client" ) ;
127129
@@ -145,48 +147,68 @@ export class StopGapWidgetDriver extends WidgetDriver {
145147 return { roomId, eventId : r . event_id } ;
146148 }
147149
148- public async readRoomEvents ( eventType : string , msgtype : string | undefined , limit : number ) : Promise < object [ ] > {
149- limit = limit > 0 ? Math . min ( limit , 25 ) : 25 ; // arbitrary choice
150-
150+ private pickRooms ( roomIds : ( string | Symbols . AnyRoom ) [ ] = null ) : Room [ ] {
151151 const client = MatrixClientPeg . get ( ) ;
152- const roomId = ActiveRoomObserver . activeRoomId ;
153- const room = client . getRoom ( roomId ) ;
154- if ( ! client || ! roomId || ! room ) throw new Error ( "Not in a room or not attached to a client" ) ;
155-
156- const results : MatrixEvent [ ] = [ ] ;
157- const events = room . getLiveTimeline ( ) . getEvents ( ) ; // timelines are most recent last
158- for ( let i = events . length - 1 ; i > 0 ; i -- ) {
159- if ( results . length >= limit ) break ;
160-
161- const ev = events [ i ] ;
162- if ( ev . getType ( ) !== eventType || ev . isState ( ) ) continue ;
163- if ( eventType === EventType . RoomMessage && msgtype && msgtype !== ev . getContent ( ) [ 'msgtype' ] ) continue ;
164- results . push ( ev ) ;
165- }
152+ if ( ! client ) throw new Error ( "Not attached to a client" ) ;
166153
167- return results . map ( e => e . getEffectiveEvent ( ) ) ;
154+ const targetRooms = roomIds
155+ ? ( roomIds . includes ( Symbols . AnyRoom ) ? client . getVisibleRooms ( ) : roomIds . map ( r => client . getRoom ( r ) ) )
156+ : [ client . getRoom ( ActiveRoomObserver . activeRoomId ) ] ;
157+ return targetRooms . filter ( r => ! ! r ) ;
168158 }
169159
170- public async readStateEvents ( eventType : string , stateKey : string | undefined , limit : number ) : Promise < object [ ] > {
171- limit = limit > 0 ? Math . min ( limit , 100 ) : 100 ; // arbitrary choice
172-
173- const client = MatrixClientPeg . get ( ) ;
174- const roomId = ActiveRoomObserver . activeRoomId ;
175- const room = client . getRoom ( roomId ) ;
176- if ( ! client || ! roomId || ! room ) throw new Error ( "Not in a room or not attached to a client" ) ;
177-
178- const results : MatrixEvent [ ] = [ ] ;
179- const state : Map < string , MatrixEvent > = room . currentState . events . get ( eventType ) ;
180- if ( state ) {
181- if ( stateKey === "" || ! ! stateKey ) {
182- const forKey = state . get ( stateKey ) ;
183- if ( forKey ) results . push ( forKey ) ;
184- } else {
185- results . push ( ...Array . from ( state . values ( ) ) ) ;
160+ public async readRoomEvents (
161+ eventType : string ,
162+ msgtype : string | undefined ,
163+ limitPerRoom : number ,
164+ roomIds : ( string | Symbols . AnyRoom ) [ ] = null ,
165+ ) : Promise < object [ ] > {
166+ limitPerRoom = limitPerRoom > 0 ? Math . min ( limitPerRoom , 25 ) : 25 ; // arbitrary choice
167+
168+ const rooms = this . pickRooms ( roomIds ) ;
169+ const allResults : IEvent [ ] = [ ] ;
170+ for ( const room of rooms ) {
171+ const results : MatrixEvent [ ] = [ ] ;
172+ const events = room . getLiveTimeline ( ) . getEvents ( ) ; // timelines are most recent last
173+ for ( let i = events . length - 1 ; i > 0 ; i -- ) {
174+ if ( results . length >= limitPerRoom ) break ;
175+
176+ const ev = events [ i ] ;
177+ if ( ev . getType ( ) !== eventType || ev . isState ( ) ) continue ;
178+ if ( eventType === EventType . RoomMessage && msgtype && msgtype !== ev . getContent ( ) [ 'msgtype' ] ) continue ;
179+ results . push ( ev ) ;
186180 }
181+
182+ results . forEach ( e => allResults . push ( e . getEffectiveEvent ( ) ) ) ;
187183 }
184+ return allResults ;
185+ }
188186
189- return results . slice ( 0 , limit ) . map ( e => e . event ) ;
187+ public async readStateEvents (
188+ eventType : string ,
189+ stateKey : string | undefined ,
190+ limitPerRoom : number ,
191+ roomIds : ( string | Symbols . AnyRoom ) [ ] = null ,
192+ ) : Promise < object [ ] > {
193+ limitPerRoom = limitPerRoom > 0 ? Math . min ( limitPerRoom , 100 ) : 100 ; // arbitrary choice
194+
195+ const rooms = this . pickRooms ( roomIds ) ;
196+ const allResults : IEvent [ ] = [ ] ;
197+ for ( const room of rooms ) {
198+ const results : MatrixEvent [ ] = [ ] ;
199+ const state : Map < string , MatrixEvent > = room . currentState . events . get ( eventType ) ;
200+ if ( state ) {
201+ if ( stateKey === "" || ! ! stateKey ) {
202+ const forKey = state . get ( stateKey ) ;
203+ if ( forKey ) results . push ( forKey ) ;
204+ } else {
205+ results . push ( ...Array . from ( state . values ( ) ) ) ;
206+ }
207+ }
208+
209+ results . slice ( 0 , limitPerRoom ) . forEach ( e => allResults . push ( e . getEffectiveEvent ( ) ) ) ;
210+ }
211+ return allResults ;
190212 }
191213
192214 public async askOpenID ( observer : SimpleObservable < IOpenIDUpdate > ) {
0 commit comments