UNPKG

4.89 kBJavaScriptView Raw
1/*
2Copyright 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-component
19 */
20
21/**
22 * Checks if a value matches a given field value, which may be a * terminated
23 * wildcard pattern.
24 * @param {String} actual_value The value to be compared
25 * @param {String} filter_value The filter pattern to be compared
26 * @return {bool} true if the actual_value matches the filter_value
27 */
28function _matches_wildcard(actual_value, filter_value) {
29 if (filter_value.endsWith("*")) {
30 const type_prefix = filter_value.slice(0, -1);
31 return actual_value.substr(0, type_prefix.length) === type_prefix;
32 } else {
33 return actual_value === filter_value;
34 }
35}
36
37/**
38 * FilterComponent is a section of a Filter definition which defines the
39 * types, rooms, senders filters etc to be applied to a particular type of resource.
40 * This is all ported over from synapse's Filter object.
41 *
42 * N.B. that synapse refers to these as 'Filters', and what js-sdk refers to as
43 * 'Filters' are referred to as 'FilterCollections'.
44 *
45 * @constructor
46 * @param {Object} filter_json the definition of this filter JSON, e.g. { 'contains_url': true }
47 */
48function FilterComponent(filter_json) {
49 this.filter_json = filter_json;
50
51 this.types = filter_json.types || null;
52 this.not_types = filter_json.not_types || [];
53
54 this.rooms = filter_json.rooms || null;
55 this.not_rooms = filter_json.not_rooms || [];
56
57 this.senders = filter_json.senders || null;
58 this.not_senders = filter_json.not_senders || [];
59
60 this.contains_url = filter_json.contains_url || null;
61}
62
63/**
64 * Checks with the filter component matches the given event
65 * @param {MatrixEvent} event event to be checked against the filter
66 * @return {bool} true if the event matches the filter
67 */
68FilterComponent.prototype.check = function(event) {
69 return this._checkFields(
70 event.getRoomId(),
71 event.getSender(),
72 event.getType(),
73 event.getContent() ? event.getContent().url !== undefined : false,
74 );
75};
76
77/**
78 * Checks whether the filter component matches the given event fields.
79 * @param {String} room_id the room_id for the event being checked
80 * @param {String} sender the sender of the event being checked
81 * @param {String} event_type the type of the event being checked
82 * @param {String} contains_url whether the event contains a content.url field
83 * @return {bool} true if the event fields match the filter
84 */
85FilterComponent.prototype._checkFields =
86 function(room_id, sender, event_type, contains_url) {
87 const literal_keys = {
88 "rooms": function(v) {
89 return room_id === v;
90 },
91 "senders": function(v) {
92 return sender === v;
93 },
94 "types": function(v) {
95 return _matches_wildcard(event_type, v);
96 },
97 };
98
99 const self = this;
100 for (let n=0; n < Object.keys(literal_keys).length; n++) {
101 const name = Object.keys(literal_keys)[n];
102 const match_func = literal_keys[name];
103 const not_name = "not_" + name;
104 const disallowed_values = self[not_name];
105 if (disallowed_values.filter(match_func).length > 0) {
106 return false;
107 }
108
109 const allowed_values = self[name];
110 if (allowed_values) {
111 if (!allowed_values.map(match_func)) {
112 return false;
113 }
114 }
115 }
116
117 const contains_url_filter = this.filter_json.contains_url;
118 if (contains_url_filter !== undefined) {
119 if (contains_url_filter !== contains_url) {
120 return false;
121 }
122 }
123
124 return true;
125};
126
127/**
128 * Filters a list of events down to those which match this filter component
129 * @param {MatrixEvent[]} events Events to be checked againt the filter component
130 * @return {MatrixEvent[]} events which matched the filter component
131 */
132FilterComponent.prototype.filter = function(events) {
133 return events.filter(this.check, this);
134};
135
136/**
137 * Returns the limit field for a given filter component, providing a default of
138 * 10 if none is otherwise specified. Cargo-culted from Synapse.
139 * @return {Number} the limit for this filter component.
140 */
141FilterComponent.prototype.limit = function() {
142 return this.filter_json.limit !== undefined ? this.filter_json.limit : 10;
143};
144
145/** The FilterComponent class */
146module.exports = FilterComponent;