FEATURE: Support regular expressions for watched words
This commit is contained in:
parent
fa41913ba5
commit
41c3941c4c
|
@ -1,5 +1,5 @@
|
|||
import WatchedWord from 'admin/models/watched-word';
|
||||
import { on, observes } from 'ember-addons/ember-computed-decorators';
|
||||
import { default as computed, on, observes } from 'ember-addons/ember-computed-decorators';
|
||||
|
||||
export default Ember.Component.extend({
|
||||
classNames: ['watched-word-form'],
|
||||
|
@ -7,6 +7,12 @@ export default Ember.Component.extend({
|
|||
actionKey: null,
|
||||
showSuccessMessage: false,
|
||||
|
||||
@computed('regularExpressions')
|
||||
placeholderKey(regularExpressions) {
|
||||
return "admin.watched_words.form.placeholder" +
|
||||
(regularExpressions ? "_regexp" : "");
|
||||
},
|
||||
|
||||
@observes('word')
|
||||
removeSuccessMessage() {
|
||||
if (this.get('showSuccessMessage') && !Ember.isEmpty(this.get('word'))) {
|
||||
|
|
|
@ -5,6 +5,7 @@ export default Ember.Controller.extend({
|
|||
filtered: false,
|
||||
showWords: false,
|
||||
disableShowWords: Ember.computed.alias('filtered'),
|
||||
regularExpressions: null,
|
||||
|
||||
filterContentNow() {
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ const WatchedWord = Discourse.Model.extend({
|
|||
|
||||
WatchedWord.reopenClass({
|
||||
findAll() {
|
||||
return ajax("/admin/logs/watched_words").then(function (list) {
|
||||
return ajax("/admin/logs/watched_words").then(list => {
|
||||
const actions = {};
|
||||
list.words.forEach(s => {
|
||||
if (!actions[s.action]) { actions[s.action] = []; }
|
||||
|
@ -27,8 +27,14 @@ WatchedWord.reopenClass({
|
|||
if (!actions[a]) { actions[a] = []; }
|
||||
});
|
||||
|
||||
return Object.keys(actions).map(function(n) {
|
||||
return Ember.Object.create({nameKey: n, name: I18n.t('admin.watched_words.actions.' + n), words: actions[n], count: actions[n].length});
|
||||
return Object.keys(actions).map(n => {
|
||||
return Ember.Object.create({
|
||||
nameKey: n,
|
||||
name: I18n.t('admin.watched_words.actions.' + n),
|
||||
words: actions[n],
|
||||
count: actions[n].length,
|
||||
regularExpressions: list.regular_expressions
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -9,6 +9,13 @@ export default Discourse.Route.extend({
|
|||
return WatchedWord.findAll();
|
||||
},
|
||||
|
||||
setupController(controller, model) {
|
||||
controller.set('model', model);
|
||||
if (model && model.length) {
|
||||
controller.set('regularExpressions', model[0].get('regularExpressions'));
|
||||
}
|
||||
},
|
||||
|
||||
afterModel(watchedWordsList) {
|
||||
this.controllerFor('adminWatchedWords').set('allWatchedWords', watchedWordsList);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<b>{{i18n 'admin.watched_words.form.label'}}</b>
|
||||
{{text-field value=word disabled=formSubmitted class="watched-word-input" autocorrect="off" autocapitalize="off" placeholderKey="admin.watched_words.form.placeholder"}}
|
||||
{{text-field value=word disabled=formSubmitted class="watched-word-input" autocorrect="off" autocapitalize="off" placeholderKey=placeholderKey}}
|
||||
{{d-button action="submit" disabled=formSubmitted label="admin.watched_words.form.add"}}
|
||||
|
||||
{{#if showSuccessMessage}}
|
||||
|
|
|
@ -2,7 +2,10 @@
|
|||
|
||||
<p class="about">{{actionDescription}}</p>
|
||||
|
||||
{{watched-word-form actionKey=actionNameKey action="recordAdded"}}
|
||||
{{watched-word-form
|
||||
actionKey=actionNameKey
|
||||
action="recordAdded"
|
||||
regularExpressions=adminWatchedWords.regularExpressions}}
|
||||
|
||||
{{watched-word-uploader uploading=uploading actionKey=actionNameKey done="uploadComplete"}}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
class WatchedWordListSerializer < ApplicationSerializer
|
||||
attributes :actions, :words
|
||||
attributes :actions, :words, :regular_expressions
|
||||
|
||||
def actions
|
||||
WatchedWord.actions.keys
|
||||
|
@ -10,4 +10,10 @@ class WatchedWordListSerializer < ApplicationSerializer
|
|||
WatchedWordSerializer.new(word, root: false)
|
||||
end
|
||||
end
|
||||
|
||||
# No point making this site setting `client: true` when it's only used
|
||||
# in the admin section
|
||||
def regular_expressions
|
||||
SiteSetting.watched_words_regular_expressions?
|
||||
end
|
||||
end
|
||||
|
|
|
@ -15,12 +15,17 @@ class WordWatcher
|
|||
def self.word_matcher_regexp(action)
|
||||
s = Discourse.cache.fetch(word_matcher_regexp_key(action), expires_in: 1.day) do
|
||||
words = words_for_action(action)
|
||||
words.empty? ? nil : '\b(' + words.map { |w| Regexp.escape(w).gsub("\\*", '\S*') }.join('|'.freeze) + ')\b'
|
||||
words.empty? ? nil : '\b(' + words.map { |w| word_to_regexp(w) }.join('|'.freeze) + ')\b'
|
||||
end
|
||||
|
||||
s.present? ? Regexp.new(s, Regexp::IGNORECASE) : nil
|
||||
end
|
||||
|
||||
def self.word_to_regexp(word)
|
||||
return word if SiteSetting.watched_words_regular_expressions?
|
||||
Regexp.escape(word).gsub("\\*", '\S*')
|
||||
end
|
||||
|
||||
def self.word_matcher_regexp_key(action)
|
||||
"watched-words-regexp:#{action}"
|
||||
end
|
||||
|
|
|
@ -3203,6 +3203,7 @@ en:
|
|||
form:
|
||||
label: 'New Word:'
|
||||
placeholder: 'full word or * as wildcard'
|
||||
placeholder_regexp: "regular expression"
|
||||
add: 'Add'
|
||||
success: 'Success'
|
||||
upload: "Upload"
|
||||
|
|
|
@ -1521,6 +1521,7 @@ en:
|
|||
code_formatting_style: "Code button in composer will default to this code formatting style"
|
||||
|
||||
max_allowed_message_recipients: "Maximum recipients allowed in a message."
|
||||
watched_words_regular_expressions: "Watched words are regular expressions."
|
||||
|
||||
default_email_digest_frequency: "How often users receive summary emails by default."
|
||||
default_include_tl0_in_digests: "Include posts from new users in summary emails by default. Users can change this in their preferences."
|
||||
|
|
|
@ -625,6 +625,8 @@ posting:
|
|||
max_allowed_message_recipients:
|
||||
default: 30
|
||||
min: 1
|
||||
watched_words_regular_expressions:
|
||||
default: false
|
||||
|
||||
email:
|
||||
email_time_window_mins:
|
||||
|
|
|
@ -47,6 +47,21 @@ describe WordWatcher do
|
|||
m = WordWatcher.new("I acknowledge you.").word_matches_for_action?(:require_approval)
|
||||
expect(m[1]).to eq("acknowledge")
|
||||
end
|
||||
|
||||
it "supports regular expressions as a site setting" do
|
||||
SiteSetting.watched_words_regular_expressions = true
|
||||
Fabricate(
|
||||
:watched_word,
|
||||
word: "tro[uo]+t",
|
||||
action: WatchedWord.actions[:require_approval]
|
||||
)
|
||||
m = WordWatcher.new("Evil Trout is cool").word_matches_for_action?(:require_approval)
|
||||
expect(m[1]).to eq("Trout")
|
||||
m = WordWatcher.new("Evil Troot is cool").word_matches_for_action?(:require_approval)
|
||||
expect(m[1]).to eq("Troot")
|
||||
m = WordWatcher.new("trooooooooot").word_matches_for_action?(:require_approval)
|
||||
expect(m[1]).to eq("trooooooooot")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in New Issue