diff --git a/app/controllers/admin/configs_controller.rb b/app/controllers/admin/configs_controller.rb index 4308a1fed..44f58e9f6 100644 --- a/app/controllers/admin/configs_controller.rb +++ b/app/controllers/admin/configs_controller.rb @@ -56,6 +56,7 @@ module Admin facebook_secret allow_email_password_registration primary_brand_color_hex + spam_trigger_terms ] allowed_params = allowed_params | diff --git a/app/lib/constants/site_config.rb b/app/lib/constants/site_config.rb index f064e3f56..8295ee485 100644 --- a/app/lib/constants/site_config.rb +++ b/app/lib/constants/site_config.rb @@ -222,6 +222,10 @@ module Constants description: "Used as the secondary logo", placeholder: "https://image.url" }, + spam_trigger_terms: { + description: "Individual (case insensitive) phrases that trigger spam alerts, comma separated.", + placeholder: "used cares near you, pokemon go hack" + }, shop_url: { description: "Used as the shop url of the community", placeholder: "https://shop.url" diff --git a/app/models/article.rb b/app/models/article.rb index 14b479c63..546a0b6bd 100644 --- a/app/models/article.rb +++ b/app/models/article.rb @@ -90,6 +90,7 @@ class Article < ApplicationRecord before_save :calculate_base_scores before_save :fetch_video_duration before_save :set_caches + before_save :create_conditional_autovomits before_create :create_password before_destroy :before_destroy_actions, prepend: true @@ -677,6 +678,17 @@ class Article < ApplicationRecord self.spaminess_rating = 0 if new_record? end + def create_conditional_autovomits + return unless SiteConfig.spam_trigger_terms.any? { |term| title.downcase.include?(term.downcase) } + + Reaction.create( + user_id: SiteConfig.mascot_user_id, + reactable_id: id, + reactable_type: "Article", + category: "vomit", + ) + end + def async_bust Articles::BustCacheWorker.perform_async(id) end diff --git a/app/models/comment.rb b/app/models/comment.rb index e181fbde9..3e3acab78 100644 --- a/app/models/comment.rb +++ b/app/models/comment.rb @@ -25,6 +25,7 @@ class Comment < ApplicationRecord before_validation :evaluate_markdown, if: -> { body_markdown } before_save :set_markdown_character_count, if: :body_markdown + before_save :create_conditional_autovomits before_create :adjust_comment_parent_based_on_depth after_create :after_create_checks after_create :notify_slack_channel_about_warned_users @@ -244,6 +245,20 @@ class Comment < ApplicationRecord Comments::SendEmailNotificationWorker.perform_async(id) end + def create_conditional_autovomits + return unless + SiteConfig.spam_trigger_terms.any? { |term| body_markdown.downcase.include?(term.downcase) } && + user.registered_at > 5.days.ago + + self.score = -1 + Reaction.create( + user_id: SiteConfig.mascot_user_id, + reactable_id: id, + reactable_type: "Comment", + category: "vomit", + ) + end + def should_send_email_notification? parent_exists? && parent_user.class.name != "Podcast" && diff --git a/app/models/reaction.rb b/app/models/reaction.rb index ed08db93e..028cd27a5 100644 --- a/app/models/reaction.rb +++ b/app/models/reaction.rb @@ -173,7 +173,7 @@ class Reaction < ApplicationRecord end def negative_reaction_from_untrusted_user? - return if user&.any_admin? + return if user&.any_admin? || user&.id == SiteConfig.mascot_user_id negative? && !user.trusted end diff --git a/app/models/site_config.rb b/app/models/site_config.rb index a350a9b1e..b00760238 100644 --- a/app/models/site_config.rb +++ b/app/models/site_config.rb @@ -117,7 +117,7 @@ class SiteConfig < RailsSettings::Base field :suggested_tags, type: :array, default: %w[] field :suggested_users, type: :array, default: %w[] - # Rate limits + # Rate limits and spam prevention field :rate_limit_follow_count_daily, type: :integer, default: 500 field :rate_limit_comment_creation, type: :integer, default: 9 field :rate_limit_listing_creation, type: :integer, default: 1 @@ -132,6 +132,8 @@ class SiteConfig < RailsSettings::Base field :rate_limit_user_update, type: :integer, default: 5 field :rate_limit_user_subscription_creation, type: :integer, default: 3 + field :spam_trigger_terms, type: :array, default: [] + # Social Media field :social_media_handles, type: :hash, default: { twitter: nil, diff --git a/app/services/notifications/new_comment/send.rb b/app/services/notifications/new_comment/send.rb index 256b1b70c..04c253311 100644 --- a/app/services/notifications/new_comment/send.rb +++ b/app/services/notifications/new_comment/send.rb @@ -14,6 +14,8 @@ module Notifications end def call + return if comment.score.negative? + user_ids = Set.new(comment_user_ids + subscribed_user_ids + top_level_user_ids + author_subscriber_user_ids) json_data = { diff --git a/app/views/admin/configs/show.html.erb b/app/views/admin/configs/show.html.erb index 68857a23b..9e184400a 100644 --- a/app/views/admin/configs/show.html.erb +++ b/app/views/admin/configs/show.html.erb @@ -834,7 +834,7 @@