diff options
author | Eugen Rochko <eugen@zeonfederated.com> | 2018-06-29 15:34:36 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-06-29 15:34:36 +0200 |
commit | cdb101340a20183a82889f811d9311c370c855e5 (patch) | |
tree | daacd56d1edbf359b0d97a926e90b999ba7f6129 /app/javascript/mastodon/selectors/index.js | |
parent | fbee9b5ac898e571e384792a92b40fa1524cf127 (diff) |
Keyword/phrase filtering (#7905)
* Add keyword filtering GET|POST /api/v1/filters GET|PUT|DELETE /api/v1/filters/:id - Irreversible filters can drop toots from home or notifications - Other filters can hide toots through the client app - Filters use a phrase valid in particular contexts, expiration * Make sure expired filters don't get applied client-side * Add missing API methods * Remove "regex filter" from column settings * Add tests * Add test for FeedManager * Add CustomFilter test * Add UI for managing filters * Add streaming API event to allow syncing filters * Fix tests
Diffstat (limited to 'app/javascript/mastodon/selectors/index.js')
-rw-r--r-- | app/javascript/mastodon/selectors/index.js | 42 |
1 files changed, 37 insertions, 5 deletions
diff --git a/app/javascript/mastodon/selectors/index.js b/app/javascript/mastodon/selectors/index.js index e47ec5183..56eca1f02 100644 --- a/app/javascript/mastodon/selectors/index.js +++ b/app/javascript/mastodon/selectors/index.js @@ -19,16 +19,44 @@ export const makeGetAccount = () => { }); }; +const toServerSideType = columnType => { + switch (columnType) { + case 'home': + case 'notifications': + case 'public': + case 'thread': + return columnType; + default: + if (columnType.indexOf('list:') > -1) { + return 'home'; + } else { + return 'public'; // community, account, hashtag + } + } +}; + +const escapeRegExp = string => + string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string + +const regexFromFilters = filters => { + if (filters.size === 0) { + return null; + } + + return new RegExp(filters.map(filter => escapeRegExp(filter.get('phrase'))).join('|'), 'i'); +}; + export const makeGetStatus = () => { return createSelector( [ - (state, id) => state.getIn(['statuses', id]), - (state, id) => state.getIn(['statuses', state.getIn(['statuses', id, 'reblog'])]), - (state, id) => state.getIn(['accounts', state.getIn(['statuses', id, 'account'])]), - (state, id) => state.getIn(['accounts', state.getIn(['statuses', state.getIn(['statuses', id, 'reblog']), 'account'])]), + (state, { id }) => state.getIn(['statuses', id]), + (state, { id }) => state.getIn(['statuses', state.getIn(['statuses', id, 'reblog'])]), + (state, { id }) => state.getIn(['accounts', state.getIn(['statuses', id, 'account'])]), + (state, { id }) => state.getIn(['accounts', state.getIn(['statuses', state.getIn(['statuses', id, 'reblog']), 'account'])]), + (state, { contextType }) => state.get('filters', ImmutableList()).filter(filter => contextType && filter.get('context').includes(toServerSideType(contextType)) && (filter.get('expires_at') === null || Date.parse(filter.get('expires_at')) > (new Date()))), ], - (statusBase, statusReblog, accountBase, accountReblog) => { + (statusBase, statusReblog, accountBase, accountReblog, filters) => { if (!statusBase) { return null; } @@ -39,9 +67,13 @@ export const makeGetStatus = () => { statusReblog = null; } + const regex = regexFromFilters(filters); + const filtered = regex && regex.test(statusBase.get('reblog') ? statusReblog.get('search_index') : statusBase.get('search_index')); + return statusBase.withMutations(map => { map.set('reblog', statusReblog); map.set('account', accountBase); + map.set('filtered', filtered); }); } ); |