mirror of
https://github.com/discourse/discourse.git
synced 2024-11-22 14:38:17 +08:00
FIX: user got notified about a mention inside a chat message quote (#24229)
When quoting a chat message in a post, if that message contains a mention, that mention should be ignored. But we've been detecting them and sending notifications to users. This PR fixes the problem. Since this fix is for the chat plugin, I had to introduce a new API for plugins: # We strip posts before detecting mentions, oneboxes, attachments etc. # We strip those elements that shouldn't be detected. For example, # a mention inside a quote should be ignored, so we strip it off. # Using this API plugins can register their own post strippers. def register_post_stripper(&block) end
This commit is contained in:
parent
179abfca1a
commit
be2eb3df44
|
@ -146,11 +146,9 @@ class PostAnalyzer
|
|||
def cooked_stripped
|
||||
@cooked_stripped ||=
|
||||
begin
|
||||
doc = Nokogiri::HTML5.fragment(cook(@raw, topic_id: @topic_id))
|
||||
doc.css(
|
||||
"pre .mention, aside.quote > .title, aside.quote .mention, aside.quote .mention-group, .onebox, .elided",
|
||||
).remove
|
||||
doc
|
||||
cooked = cook(@raw, topic_id: @topic_id)
|
||||
fragment = Nokogiri::HTML5.fragment(cooked)
|
||||
PostStripper.strip(fragment)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
28
app/models/post_stripper.rb
Normal file
28
app/models/post_stripper.rb
Normal file
|
@ -0,0 +1,28 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
# We strip posts before detecting mentions, oneboxes, attachments etc.
|
||||
# We strip those elements that shouldn't be detected. For example,
|
||||
# a mention inside a quote should be ignored, so we strip it off.
|
||||
class PostStripper
|
||||
def self.strip(nokogiri_fragment)
|
||||
run_core_strippers(nokogiri_fragment)
|
||||
run_plugin_strippers(nokogiri_fragment)
|
||||
nokogiri_fragment
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def self.run_core_strippers(nokogiri_fragment)
|
||||
nokogiri_fragment.css(
|
||||
"pre .mention, aside.quote > .title, aside.quote .mention, aside.quote .mention-group, .onebox, .elided",
|
||||
).remove
|
||||
end
|
||||
|
||||
def self.run_plugin_strippers(nokogiri_fragment)
|
||||
DiscoursePluginRegistry.post_strippers.each do |stripper|
|
||||
stripper[:block].call(nokogiri_fragment)
|
||||
end
|
||||
end
|
||||
|
||||
private_class_method :run_core_strippers, :run_plugin_strippers
|
||||
end
|
|
@ -122,6 +122,8 @@ class DiscoursePluginRegistry
|
|||
|
||||
define_filtered_register :post_action_notify_user_handlers
|
||||
|
||||
define_filtered_register :post_strippers
|
||||
|
||||
def self.register_auth_provider(auth_provider)
|
||||
self.auth_providers << auth_provider
|
||||
end
|
||||
|
|
|
@ -1254,6 +1254,14 @@ class Plugin::Instance
|
|||
DiscoursePluginRegistry.register_post_action_notify_user_handler(handler, self)
|
||||
end
|
||||
|
||||
# We strip posts before detecting mentions, oneboxes, attachments etc.
|
||||
# We strip those elements that shouldn't be detected. For example,
|
||||
# a mention inside a quote should be ignored, so we strip it off.
|
||||
# Using this API plugins can register their own post strippers.
|
||||
def register_post_stripper(&block)
|
||||
DiscoursePluginRegistry.register_post_stripper({ block: block }, self)
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def self.js_path
|
||||
|
|
|
@ -493,6 +493,10 @@ after_initialize do
|
|||
register_hashtag_type_priority_for_context("tag", "chat-composer", 50)
|
||||
register_hashtag_type_priority_for_context("channel", "topic-composer", 10)
|
||||
|
||||
register_post_stripper do |nokogiri_fragment|
|
||||
nokogiri_fragment.css(".chat-transcript .mention").remove
|
||||
end
|
||||
|
||||
Site.markdown_additional_options["chat"] = {
|
||||
limited_pretty_text_features: Chat::Message::MARKDOWN_FEATURES,
|
||||
limited_pretty_text_markdown_rules: Chat::Message::MARKDOWN_IT_RULES,
|
||||
|
|
54
spec/models/post_stripper_spec.rb
Normal file
54
spec/models/post_stripper_spec.rb
Normal file
|
@ -0,0 +1,54 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
RSpec.describe PostStripper do
|
||||
it "strips mentions in quotes" do
|
||||
mention = '<a class="mention">@andrei</a>'
|
||||
cooked = "<aside class='quote'>#{mention}</aside>"
|
||||
fragment = Nokogiri::HTML5.fragment(cooked)
|
||||
|
||||
PostStripper.strip(fragment)
|
||||
|
||||
expect(fragment.to_s).to_not include(mention)
|
||||
end
|
||||
|
||||
it "strips group mentions in quotes" do
|
||||
group_mention = '<a class="mention-group">@moderators</a>'
|
||||
cooked = "<aside class='quote'>#{group_mention}</aside>"
|
||||
fragment = Nokogiri::HTML5.fragment(cooked)
|
||||
|
||||
PostStripper.strip(fragment)
|
||||
|
||||
expect(fragment.to_s).to_not include(group_mention)
|
||||
end
|
||||
|
||||
it "strips oneboxes" do
|
||||
onebox =
|
||||
'<aside class="onebox">
|
||||
Onebox content
|
||||
</aside>'
|
||||
cooked = "<p>#{onebox}</p>"
|
||||
fragment = Nokogiri::HTML5.fragment(cooked)
|
||||
|
||||
PostStripper.strip(fragment)
|
||||
|
||||
expect(fragment.to_s).to_not include(onebox)
|
||||
end
|
||||
|
||||
context "with plugins" do
|
||||
after { DiscoursePluginRegistry.reset_register!(:post_strippers) }
|
||||
|
||||
it "runs strippers registered by plugins" do
|
||||
plugin_element = '<div class="plugin_class"></div>'
|
||||
|
||||
block = Proc.new { |nokogiri_fragment| nokogiri_fragment.css(".plugin_class").remove }
|
||||
plugin = OpenStruct.new(enabled?: true)
|
||||
DiscoursePluginRegistry.register_post_stripper({ block: block }, plugin)
|
||||
|
||||
fragment = Nokogiri::HTML5.fragment("<p>#{plugin_element}</p>")
|
||||
|
||||
PostStripper.strip(fragment)
|
||||
|
||||
expect(fragment.to_s).to_not include(plugin_element)
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue
Block a user