UNPKG

5.99 kBJavaScriptView Raw
1/*
2Copyright 2015, 2016 OpenMarket Ltd
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15*/
16"use strict";
17/**
18 * @module filter
19 */
20
21const FilterComponent = require("./filter-component");
22
23/**
24 * @param {Object} obj
25 * @param {string} keyNesting
26 * @param {*} val
27 */
28function setProp(obj, keyNesting, val) {
29 const nestedKeys = keyNesting.split(".");
30 let currentObj = obj;
31 for (let i = 0; i < (nestedKeys.length - 1); i++) {
32 if (!currentObj[nestedKeys[i]]) {
33 currentObj[nestedKeys[i]] = {};
34 }
35 currentObj = currentObj[nestedKeys[i]];
36 }
37 currentObj[nestedKeys[nestedKeys.length - 1]] = val;
38}
39
40/**
41 * Construct a new Filter.
42 * @constructor
43 * @param {string} userId The user ID for this filter.
44 * @param {string=} filterId The filter ID if known.
45 * @prop {string} userId The user ID of the filter
46 * @prop {?string} filterId The filter ID
47 */
48function Filter(userId, filterId) {
49 this.userId = userId;
50 this.filterId = filterId;
51 this.definition = {};
52}
53
54Filter.LAZY_LOADING_MESSAGES_FILTER = {
55 lazy_load_members: true,
56};
57
58Filter.LAZY_LOADING_SYNC_FILTER = {
59 room: {
60 state: Filter.LAZY_LOADING_MESSAGES_FILTER,
61 },
62};
63
64
65/**
66 * Get the ID of this filter on your homeserver (if known)
67 * @return {?Number} The filter ID
68 */
69Filter.prototype.getFilterId = function() {
70 return this.filterId;
71};
72
73/**
74 * Get the JSON body of the filter.
75 * @return {Object} The filter definition
76 */
77Filter.prototype.getDefinition = function() {
78 return this.definition;
79};
80
81/**
82 * Set the JSON body of the filter
83 * @param {Object} definition The filter definition
84 */
85Filter.prototype.setDefinition = function(definition) {
86 this.definition = definition;
87
88 // This is all ported from synapse's FilterCollection()
89
90 // definitions look something like:
91 // {
92 // "room": {
93 // "rooms": ["!abcde:example.com"],
94 // "not_rooms": ["!123456:example.com"],
95 // "state": {
96 // "types": ["m.room.*"],
97 // "not_rooms": ["!726s6s6q:example.com"],
98 // },
99 // "timeline": {
100 // "limit": 10,
101 // "types": ["m.room.message"],
102 // "not_rooms": ["!726s6s6q:example.com"],
103 // "not_senders": ["@spam:example.com"]
104 // "contains_url": true
105 // },
106 // "ephemeral": {
107 // "types": ["m.receipt", "m.typing"],
108 // "not_rooms": ["!726s6s6q:example.com"],
109 // "not_senders": ["@spam:example.com"]
110 // }
111 // },
112 // "presence": {
113 // "types": ["m.presence"],
114 // "not_senders": ["@alice:example.com"]
115 // },
116 // "event_format": "client",
117 // "event_fields": ["type", "content", "sender"]
118 // }
119
120 const room_filter_json = definition.room;
121
122 // consider the top level rooms/not_rooms filter
123 const room_filter_fields = {};
124 if (room_filter_json) {
125 if (room_filter_json.rooms) {
126 room_filter_fields.rooms = room_filter_json.rooms;
127 }
128 if (room_filter_json.rooms) {
129 room_filter_fields.not_rooms = room_filter_json.not_rooms;
130 }
131
132 this._include_leave = room_filter_json.include_leave || false;
133 }
134
135 this._room_filter = new FilterComponent(room_filter_fields);
136 this._room_timeline_filter = new FilterComponent(
137 room_filter_json ? (room_filter_json.timeline || {}) : {},
138 );
139
140 // don't bother porting this from synapse yet:
141 // this._room_state_filter =
142 // new FilterComponent(room_filter_json.state || {});
143 // this._room_ephemeral_filter =
144 // new FilterComponent(room_filter_json.ephemeral || {});
145 // this._room_account_data_filter =
146 // new FilterComponent(room_filter_json.account_data || {});
147 // this._presence_filter =
148 // new FilterComponent(definition.presence || {});
149 // this._account_data_filter =
150 // new FilterComponent(definition.account_data || {});
151};
152
153/**
154 * Get the room.timeline filter component of the filter
155 * @return {FilterComponent} room timeline filter component
156 */
157Filter.prototype.getRoomTimelineFilterComponent = function() {
158 return this._room_timeline_filter;
159};
160
161/**
162 * Filter the list of events based on whether they are allowed in a timeline
163 * based on this filter
164 * @param {MatrixEvent[]} events the list of events being filtered
165 * @return {MatrixEvent[]} the list of events which match the filter
166 */
167Filter.prototype.filterRoomTimeline = function(events) {
168 return this._room_timeline_filter.filter(this._room_filter.filter(events));
169};
170
171/**
172 * Set the max number of events to return for each room's timeline.
173 * @param {Number} limit The max number of events to return for each room.
174 */
175Filter.prototype.setTimelineLimit = function(limit) {
176 setProp(this.definition, "room.timeline.limit", limit);
177};
178
179/**
180 * Control whether left rooms should be included in responses.
181 * @param {boolean} includeLeave True to make rooms the user has left appear
182 * in responses.
183 */
184Filter.prototype.setIncludeLeaveRooms = function(includeLeave) {
185 setProp(this.definition, "room.include_leave", includeLeave);
186};
187
188/**
189 * Create a filter from existing data.
190 * @static
191 * @param {string} userId
192 * @param {string} filterId
193 * @param {Object} jsonObj
194 * @return {Filter}
195 */
196Filter.fromJson = function(userId, filterId, jsonObj) {
197 const filter = new Filter(userId, filterId);
198 filter.setDefinition(jsonObj);
199 return filter;
200};
201
202/** The Filter class */
203module.exports = Filter;