commit
						a2612d0d38
					
				
							
								
								
									
										64
									
								
								app/controllers/settings/keyword_mutes_controller.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								app/controllers/settings/keyword_mutes_controller.rb
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,64 @@ | ||||
| # frozen_string_literal: true | ||||
| 
 | ||||
| class Settings::KeywordMutesController < ApplicationController | ||||
|   layout 'admin' | ||||
| 
 | ||||
|   before_action :authenticate_user! | ||||
|   before_action :load_keyword_mute, only: [:edit, :update, :destroy] | ||||
| 
 | ||||
|   def index | ||||
|     @keyword_mutes = paginated_keyword_mutes_for_account | ||||
|   end | ||||
| 
 | ||||
|   def new | ||||
|     @keyword_mute = keyword_mutes_for_account.build | ||||
|   end | ||||
| 
 | ||||
|   def create | ||||
|     @keyword_mute = keyword_mutes_for_account.create(keyword_mute_params) | ||||
| 
 | ||||
|     if @keyword_mute.persisted? | ||||
|       redirect_to settings_keyword_mutes_path, notice: I18n.t('generic.changes_saved_msg') | ||||
|     else | ||||
|       render :new | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|   def update | ||||
|     if @keyword_mute.update(keyword_mute_params) | ||||
|       redirect_to settings_keyword_mutes_path, notice: I18n.t('generic.changes_saved_msg') | ||||
|     else | ||||
|       render :edit | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|   def destroy | ||||
|     @keyword_mute.destroy! | ||||
| 
 | ||||
|     redirect_to settings_keyword_mutes_path, notice: I18n.t('generic.changes_saved_msg') | ||||
|   end | ||||
| 
 | ||||
|   def destroy_all | ||||
|     keyword_mutes_for_account.delete_all | ||||
| 
 | ||||
|     redirect_to settings_keyword_mutes_path, notice: I18n.t('generic.changes_saved_msg') | ||||
|   end | ||||
| 
 | ||||
|   private | ||||
| 
 | ||||
|   def keyword_mutes_for_account | ||||
|     Glitch::KeywordMute.where(account: current_account) | ||||
|   end | ||||
| 
 | ||||
|   def load_keyword_mute | ||||
|     @keyword_mute = keyword_mutes_for_account.find(params[:id]) | ||||
|   end | ||||
| 
 | ||||
|   def keyword_mute_params | ||||
|     params.require(:keyword_mute).permit(:keyword, :whole_word) | ||||
|   end | ||||
| 
 | ||||
|   def paginated_keyword_mutes_for_account | ||||
|     keyword_mutes_for_account.order(:keyword).page params[:page] | ||||
|   end | ||||
| end | ||||
							
								
								
									
										2
									
								
								app/helpers/settings/keyword_mutes_helper.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								app/helpers/settings/keyword_mutes_helper.rb
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,2 @@ | ||||
| module Settings::KeywordMutesHelper | ||||
| end | ||||
| @ -141,6 +141,8 @@ class FeedManager | ||||
|     return false if receiver_id == status.account_id | ||||
|     return true  if status.reply? && (status.in_reply_to_id.nil? || status.in_reply_to_account_id.nil?) | ||||
| 
 | ||||
|     return true if keyword_filter?(status, Glitch::KeywordMute.matcher_for(receiver_id)) | ||||
| 
 | ||||
|     check_for_mutes = [status.account_id] | ||||
|     check_for_mutes.concat(status.mentions.pluck(:account_id)) | ||||
|     check_for_mutes.concat([status.reblog.account_id]) if status.reblog? | ||||
| @ -166,6 +168,18 @@ class FeedManager | ||||
|     false | ||||
|   end | ||||
| 
 | ||||
|   def keyword_filter?(status, matcher) | ||||
|     should_filter   = matcher =~ status.text | ||||
|     should_filter ||= matcher =~ status.spoiler_text | ||||
| 
 | ||||
|     if status.reblog? | ||||
|       should_filter ||= matcher =~ status.reblog.text | ||||
|       should_filter ||= matcher =~ status.reblog.spoiler_text | ||||
|     end | ||||
| 
 | ||||
|     !!should_filter | ||||
|   end | ||||
| 
 | ||||
|   def filter_from_mentions?(status, receiver_id) | ||||
|     return true if receiver_id == status.account_id | ||||
| 
 | ||||
| @ -175,6 +189,7 @@ class FeedManager | ||||
| 
 | ||||
|     should_filter   = Block.where(account_id: receiver_id, target_account_id: check_for_blocks).any?                                     # Filter if it's from someone I blocked, in reply to someone I blocked, or mentioning someone I blocked | ||||
|     should_filter ||= (status.account.silenced? && !Follow.where(account_id: receiver_id, target_account_id: status.account_id).exists?) # of if the account is silenced and I'm not following them | ||||
|     should_filter ||= keyword_filter?(status, Glitch::KeywordMute.matcher_for(receiver_id))                                              # or if the mention contains a muted keyword | ||||
| 
 | ||||
|     should_filter | ||||
|   end | ||||
|  | ||||
							
								
								
									
										7
									
								
								app/models/glitch.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								app/models/glitch.rb
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,7 @@ | ||||
| # frozen_string_literal: true | ||||
| 
 | ||||
| module Glitch | ||||
|   def self.table_name_prefix | ||||
|     'glitch_' | ||||
|   end | ||||
| end | ||||
							
								
								
									
										66
									
								
								app/models/glitch/keyword_mute.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								app/models/glitch/keyword_mute.rb
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,66 @@ | ||||
| # frozen_string_literal: true | ||||
| # == Schema Information | ||||
| # | ||||
| # Table name: glitch_keyword_mutes | ||||
| # | ||||
| #  id         :integer          not null, primary key | ||||
| #  account_id :integer          not null | ||||
| #  keyword    :string           not null | ||||
| #  whole_word :boolean          default(TRUE), not null | ||||
| #  created_at :datetime         not null | ||||
| #  updated_at :datetime         not null | ||||
| # | ||||
| 
 | ||||
| class Glitch::KeywordMute < ApplicationRecord | ||||
|   belongs_to :account, required: true | ||||
| 
 | ||||
|   validates_presence_of :keyword | ||||
| 
 | ||||
|   after_commit :invalidate_cached_matcher | ||||
| 
 | ||||
|   def self.matcher_for(account_id) | ||||
|     Matcher.new(account_id) | ||||
|   end | ||||
| 
 | ||||
|   private | ||||
| 
 | ||||
|   def invalidate_cached_matcher | ||||
|     Rails.cache.delete("keyword_mutes:regex:#{account_id}") | ||||
|   end | ||||
| 
 | ||||
|   class Matcher | ||||
|     attr_reader :account_id | ||||
|     attr_reader :regex | ||||
| 
 | ||||
|     def initialize(account_id) | ||||
|       @account_id = account_id | ||||
|       regex_text = Rails.cache.fetch("keyword_mutes:regex:#{account_id}") { regex_text_for_account } | ||||
|       @regex = /#{regex_text}/i | ||||
|     end | ||||
| 
 | ||||
|     def =~(str) | ||||
|       regex =~ str | ||||
|     end | ||||
| 
 | ||||
|     private | ||||
| 
 | ||||
|     def keywords | ||||
|       Glitch::KeywordMute.where(account_id: account_id).select(:keyword, :id, :whole_word) | ||||
|     end | ||||
| 
 | ||||
|     def regex_text_for_account | ||||
|       kws = keywords.find_each.with_object([]) do |kw, a| | ||||
|         a << (kw.whole_word ? boundary_regex_for_keyword(kw.keyword) : kw.keyword) | ||||
|       end | ||||
| 
 | ||||
|       Regexp.union(kws).source | ||||
|     end | ||||
| 
 | ||||
|     def boundary_regex_for_keyword(keyword) | ||||
|       sb = keyword =~ /\A[[:word:]]/ ? '\b' : '' | ||||
|       eb = keyword =~ /[[:word:]]\Z/ ? '\b' : '' | ||||
| 
 | ||||
|       /#{sb}#{Regexp.escape(keyword)}#{eb}/ | ||||
|     end | ||||
|   end | ||||
| end | ||||
							
								
								
									
										11
									
								
								app/views/settings/keyword_mutes/_fields.html.haml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								app/views/settings/keyword_mutes/_fields.html.haml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,11 @@ | ||||
| .fields-group | ||||
|   = f.input :keyword | ||||
|   = f.check_box :whole_word | ||||
|   = f.label :whole_word, t('keyword_mutes.match_whole_word') | ||||
| 
 | ||||
| .actions | ||||
|   - if f.object.persisted? | ||||
|     = f.button :button, t('generic.save_changes'), type: :submit | ||||
|     = link_to t('keyword_mutes.remove'), settings_keyword_mute_path(f.object), class: 'negative button', method: :delete, data: { confirm: t('admin.accounts.are_you_sure') } | ||||
|   - else | ||||
|     = f.button :button, t('keyword_mutes.add_keyword'), type: :submit | ||||
							
								
								
									
										10
									
								
								app/views/settings/keyword_mutes/_keyword_mute.html.haml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								app/views/settings/keyword_mutes/_keyword_mute.html.haml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,10 @@ | ||||
| %tr | ||||
|   %td | ||||
|     = keyword_mute.keyword | ||||
|   %td | ||||
|     - if keyword_mute.whole_word | ||||
|       %i.fa.fa-check | ||||
|   %td | ||||
|     = table_link_to 'edit', t('keyword_mutes.edit'), edit_settings_keyword_mute_path(keyword_mute) | ||||
|   %td | ||||
|     = table_link_to 'times', t('keyword_mutes.remove'), settings_keyword_mute_path(keyword_mute), method: :delete, data: { confirm: t('admin.accounts.are_you_sure') } | ||||
							
								
								
									
										6
									
								
								app/views/settings/keyword_mutes/edit.html.haml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								app/views/settings/keyword_mutes/edit.html.haml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,6 @@ | ||||
| - content_for :page_title do | ||||
|   = t('keyword_mutes.edit_keyword') | ||||
| 
 | ||||
| = simple_form_for @keyword_mute, url: settings_keyword_mute_path(@keyword_mute), as: :keyword_mute do |f| | ||||
|   = render 'shared/error_messages', object: @keyword_mute | ||||
|   = render 'fields', f: f | ||||
							
								
								
									
										18
									
								
								app/views/settings/keyword_mutes/index.html.haml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								app/views/settings/keyword_mutes/index.html.haml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,18 @@ | ||||
| - content_for :page_title do | ||||
|   = t('settings.keyword_mutes') | ||||
| 
 | ||||
| .table-wrapper | ||||
|   %table.table | ||||
|     %thead | ||||
|       %tr | ||||
|         %th= t('keyword_mutes.keyword') | ||||
|         %th= t('keyword_mutes.match_whole_word') | ||||
|         %th | ||||
|         %th | ||||
|       %tbody | ||||
|         = render partial: 'keyword_mute', collection: @keyword_mutes, as: :keyword_mute | ||||
| 
 | ||||
| = paginate @keyword_mutes | ||||
| .simple_form | ||||
|   = link_to t('keyword_mutes.add_keyword'), new_settings_keyword_mute_path, class: 'button' | ||||
|   = link_to t('keyword_mutes.remove_all'), destroy_all_settings_keyword_mutes_path, class: 'button negative', method: :delete, data: { confirm: t('admin.accounts.are_you_sure') } | ||||
							
								
								
									
										6
									
								
								app/views/settings/keyword_mutes/new.html.haml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								app/views/settings/keyword_mutes/new.html.haml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,6 @@ | ||||
| - content_for :page_title do | ||||
|   = t('keyword_mutes.add_keyword') | ||||
| 
 | ||||
| = simple_form_for @keyword_mute, url: settings_keyword_mutes_path, as: :keyword_mute do |f| | ||||
|   = render 'shared/error_messages', object: @keyword_mute | ||||
|   = render 'fields', f: f | ||||
| @ -373,6 +373,14 @@ en: | ||||
|       following: Following list | ||||
|       muting: Muting list | ||||
|     upload: Upload | ||||
|   keyword_mutes: | ||||
|     add_keyword: Add keyword | ||||
|     edit: Edit | ||||
|     edit_keyword: Edit keyword | ||||
|     keyword: Keyword | ||||
|     match_whole_word: Match whole word | ||||
|     remove: Remove | ||||
|     remove_all: Remove all | ||||
|   landing_strip_html: "<strong>%{name}</strong> is a user on %{link_to_root_path}. You can follow them or interact with them if you have an account anywhere in the fediverse." | ||||
|   landing_strip_signup_html: If you don't, you can <a href="%{sign_up_path}">sign up here</a>. | ||||
|   media_attachments: | ||||
| @ -491,6 +499,7 @@ en: | ||||
|     export: Data export | ||||
|     followers: Authorized followers | ||||
|     import: Import | ||||
|     keyword_mutes: Muted keywords | ||||
|     notifications: Notifications | ||||
|     preferences: Preferences | ||||
|     settings: Settings | ||||
|  | ||||
| @ -7,6 +7,7 @@ SimpleNavigation::Configuration.run do |navigation| | ||||
|     primary.item :settings, safe_join([fa_icon('cog fw'), t('settings.settings')]), settings_profile_url do |settings| | ||||
|       settings.item :profile, safe_join([fa_icon('user fw'), t('settings.edit_profile')]), settings_profile_url | ||||
|       settings.item :preferences, safe_join([fa_icon('sliders fw'), t('settings.preferences')]), settings_preferences_url | ||||
|       settings.item :keyword_mutes, safe_join([fa_icon('volume-off fw'), t('settings.keyword_mutes')]), settings_keyword_mutes_url | ||||
|       settings.item :notifications, safe_join([fa_icon('bell fw'), t('settings.notifications')]), settings_notifications_url | ||||
|       settings.item :password, safe_join([fa_icon('lock fw'), t('auth.change_password')]), edit_user_registration_url, highlights_on: %r{/auth/edit|/settings/delete} | ||||
|       settings.item :two_factor_authentication, safe_join([fa_icon('mobile fw'), t('settings.two_factor_authentication')]), settings_two_factor_authentication_url, highlights_on: %r{/settings/two_factor_authentication} | ||||
|  | ||||
| @ -66,6 +66,13 @@ Rails.application.routes.draw do | ||||
| 
 | ||||
|   namespace :settings do | ||||
|     resource :profile, only: [:show, :update] | ||||
| 
 | ||||
|     resources :keyword_mutes do | ||||
|       collection do | ||||
|         delete :destroy_all | ||||
|       end | ||||
|     end | ||||
| 
 | ||||
|     resource :preferences, only: [:show, :update] | ||||
|     resource :notifications, only: [:show, :update] | ||||
|     resource :import, only: [:show, :create] | ||||
|  | ||||
							
								
								
									
										12
									
								
								db/migrate/20171009222537_create_keyword_mutes.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								db/migrate/20171009222537_create_keyword_mutes.rb
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,12 @@ | ||||
| class CreateKeywordMutes < ActiveRecord::Migration[5.1] | ||||
|   def change | ||||
|     create_table :keyword_mutes do |t| | ||||
|       t.references :account, null: false | ||||
|       t.string :keyword, null: false | ||||
|       t.boolean :whole_word, null: false, default: true | ||||
|       t.timestamps | ||||
|     end | ||||
| 
 | ||||
|     add_foreign_key :keyword_mutes, :accounts, on_delete: :cascade | ||||
|   end | ||||
| end | ||||
| @ -0,0 +1,7 @@ | ||||
| class MoveKeywordMutesIntoGlitchNamespace < ActiveRecord::Migration[5.1] | ||||
|   def change | ||||
|     safety_assured do | ||||
|       rename_table :keyword_mutes, :glitch_keyword_mutes | ||||
|     end | ||||
|   end | ||||
| end | ||||
							
								
								
									
										12
									
								
								db/schema.rb
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								db/schema.rb
									
									
									
									
									
								
							| @ -10,7 +10,7 @@ | ||||
| # | ||||
| # It's strongly recommended that you check this file into your version control system. | ||||
| 
 | ||||
| ActiveRecord::Schema.define(version: 20171010025614) do | ||||
| ActiveRecord::Schema.define(version: 20171021191900) do | ||||
| 
 | ||||
|   # These are extensions that must be enabled in order to support this database | ||||
|   enable_extension "plpgsql" | ||||
| @ -155,6 +155,15 @@ ActiveRecord::Schema.define(version: 20171010025614) do | ||||
|     t.index ["account_id", "target_account_id"], name: "index_follows_on_account_id_and_target_account_id", unique: true | ||||
|   end | ||||
| 
 | ||||
|   create_table "glitch_keyword_mutes", force: :cascade do |t| | ||||
|     t.bigint "account_id", null: false | ||||
|     t.string "keyword", null: false | ||||
|     t.boolean "whole_word", default: true, null: false | ||||
|     t.datetime "created_at", null: false | ||||
|     t.datetime "updated_at", null: false | ||||
|     t.index ["account_id"], name: "index_glitch_keyword_mutes_on_account_id" | ||||
|   end | ||||
| 
 | ||||
|   create_table "imports", force: :cascade do |t| | ||||
|     t.integer "type", null: false | ||||
|     t.boolean "approved", default: false, null: false | ||||
| @ -472,6 +481,7 @@ ActiveRecord::Schema.define(version: 20171010025614) do | ||||
|   add_foreign_key "follow_requests", "accounts", name: "fk_76d644b0e7", on_delete: :cascade | ||||
|   add_foreign_key "follows", "accounts", column: "target_account_id", name: "fk_745ca29eac", on_delete: :cascade | ||||
|   add_foreign_key "follows", "accounts", name: "fk_32ed1b5560", on_delete: :cascade | ||||
|   add_foreign_key "glitch_keyword_mutes", "accounts", on_delete: :cascade | ||||
|   add_foreign_key "imports", "accounts", name: "fk_6db1b6e408", on_delete: :cascade | ||||
|   add_foreign_key "media_attachments", "accounts", name: "fk_96dd81e81b", on_delete: :nullify | ||||
|   add_foreign_key "media_attachments", "statuses", on_delete: :nullify | ||||
|  | ||||
| @ -0,0 +1,5 @@ | ||||
| require 'rails_helper' | ||||
| 
 | ||||
| RSpec.describe Settings::KeywordMutesController, type: :controller do | ||||
| 
 | ||||
| end | ||||
							
								
								
									
										2
									
								
								spec/fabricators/glitch_keyword_mute_fabricator.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								spec/fabricators/glitch_keyword_mute_fabricator.rb
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,2 @@ | ||||
| Fabricator('Glitch::KeywordMute') do | ||||
| end | ||||
							
								
								
									
										15
									
								
								spec/helpers/settings/keyword_mutes_helper_spec.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								spec/helpers/settings/keyword_mutes_helper_spec.rb
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,15 @@ | ||||
| require 'rails_helper' | ||||
| 
 | ||||
| # Specs in this file have access to a helper object that includes | ||||
| # the Settings::KeywordMutesHelper. For example: | ||||
| # | ||||
| # describe Settings::KeywordMutesHelper do | ||||
| #   describe "string concat" do | ||||
| #     it "concats two strings with spaces" do | ||||
| #       expect(helper.concat_strings("this","that")).to eq("this that") | ||||
| #     end | ||||
| #   end | ||||
| # end | ||||
| RSpec.describe Settings::KeywordMutesHelper, type: :helper do | ||||
|   pending "add some examples to (or delete) #{__FILE__}" | ||||
| end | ||||
| @ -119,6 +119,44 @@ RSpec.describe FeedManager do | ||||
|         reblog = Fabricate(:status, reblog: status, account: jeff) | ||||
|         expect(FeedManager.instance.filter?(:home, reblog, alice.id)).to be true | ||||
|       end | ||||
| 
 | ||||
|       it 'returns true for a status containing a muted keyword' do | ||||
|         Fabricate('Glitch::KeywordMute', account: alice, keyword: 'take') | ||||
|         status = Fabricate(:status, text: 'This is a hot take', account: bob) | ||||
| 
 | ||||
|         expect(FeedManager.instance.filter?(:home, status, alice.id)).to be true | ||||
|       end | ||||
| 
 | ||||
|       it 'returns true for a reply containing a muted keyword' do | ||||
|         Fabricate('Glitch::KeywordMute', account: alice, keyword: 'take') | ||||
|         s1 = Fabricate(:status, text: 'Something', account: alice) | ||||
|         s2 = Fabricate(:status, text: 'This is a hot take', thread: s1, account: bob) | ||||
| 
 | ||||
|         expect(FeedManager.instance.filter?(:home, s2, alice.id)).to be true | ||||
|       end | ||||
| 
 | ||||
|       it 'returns true for a status whose spoiler text contains a muted keyword' do | ||||
|         Fabricate('Glitch::KeywordMute', account: alice, keyword: 'take') | ||||
|         status = Fabricate(:status, spoiler_text: 'This is a hot take', account: bob) | ||||
| 
 | ||||
|         expect(FeedManager.instance.filter?(:home, status, alice.id)).to be true | ||||
|       end | ||||
| 
 | ||||
|       it 'returns true for a reblog containing a muted keyword' do | ||||
|         Fabricate('Glitch::KeywordMute', account: alice, keyword: 'take') | ||||
|         status = Fabricate(:status, text: 'This is a hot take', account: bob) | ||||
|         reblog = Fabricate(:status, reblog: status, account: jeff) | ||||
| 
 | ||||
|         expect(FeedManager.instance.filter?(:home, reblog, alice.id)).to be true | ||||
|       end | ||||
| 
 | ||||
|       it 'returns true for a reblog whose spoiler text contains a muted keyword' do | ||||
|         Fabricate('Glitch::KeywordMute', account: alice, keyword: 'take') | ||||
|         status = Fabricate(:status, spoiler_text: 'This is a hot take', account: bob) | ||||
|         reblog = Fabricate(:status, reblog: status, account: jeff) | ||||
| 
 | ||||
|         expect(FeedManager.instance.filter?(:home, reblog, alice.id)).to be true | ||||
|       end | ||||
|     end | ||||
| 
 | ||||
|     context 'for mentions feed' do | ||||
| @ -147,6 +185,13 @@ RSpec.describe FeedManager do | ||||
|         bob.follow!(alice) | ||||
|         expect(FeedManager.instance.filter?(:mentions, status, bob.id)).to be false | ||||
|       end | ||||
| 
 | ||||
|       it 'returns true for status that contains a muted keyword' do | ||||
|         Fabricate('Glitch::KeywordMute', account: bob, keyword: 'take') | ||||
|         status = Fabricate(:status, text: 'This is a hot take', account: alice) | ||||
|         bob.follow!(alice) | ||||
|         expect(FeedManager.instance.filter?(:mentions, status, bob.id)).to be true | ||||
|       end | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										89
									
								
								spec/models/glitch/keyword_mute_spec.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								spec/models/glitch/keyword_mute_spec.rb
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,89 @@ | ||||
| require 'rails_helper' | ||||
| 
 | ||||
| RSpec.describe Glitch::KeywordMute, type: :model do | ||||
|   let(:alice) { Fabricate(:account, username: 'alice').tap(&:save!) } | ||||
|   let(:bob) { Fabricate(:account, username: 'bob').tap(&:save!) } | ||||
| 
 | ||||
|   describe '.matcher_for' do | ||||
|     let(:matcher) { Glitch::KeywordMute.matcher_for(alice) } | ||||
| 
 | ||||
|     describe 'with no mutes' do | ||||
|       before do | ||||
|         Glitch::KeywordMute.delete_all | ||||
|       end | ||||
| 
 | ||||
|       it 'does not match' do | ||||
|         expect(matcher =~ 'This is a hot take').to be_falsy | ||||
|       end | ||||
|     end | ||||
| 
 | ||||
|     describe 'with mutes' do | ||||
|       it 'does not match keywords set by a different account' do | ||||
|         Glitch::KeywordMute.create!(account: bob, keyword: 'take') | ||||
| 
 | ||||
|         expect(matcher =~ 'This is a hot take').to be_falsy | ||||
|       end | ||||
| 
 | ||||
|       it 'does not match if no keywords match the status text' do | ||||
|         Glitch::KeywordMute.create!(account: alice, keyword: 'cold') | ||||
| 
 | ||||
|         expect(matcher =~ 'This is a hot take').to be_falsy | ||||
|       end | ||||
| 
 | ||||
|       it 'considers word boundaries when matching' do | ||||
|         Glitch::KeywordMute.create!(account: alice, keyword: 'bob', whole_word: true) | ||||
| 
 | ||||
|         expect(matcher =~ 'bobcats').to be_falsy | ||||
|       end | ||||
| 
 | ||||
|       it 'matches substrings if whole_word is false' do | ||||
|         Glitch::KeywordMute.create!(account: alice, keyword: 'take', whole_word: false) | ||||
| 
 | ||||
|         expect(matcher =~ 'This is a shiitake mushroom').to be_truthy | ||||
|       end | ||||
| 
 | ||||
|       it 'matches keywords at the beginning of the text' do | ||||
|         Glitch::KeywordMute.create!(account: alice, keyword: 'take') | ||||
| 
 | ||||
|         expect(matcher =~ 'Take this').to be_truthy | ||||
|       end | ||||
| 
 | ||||
|       it 'matches keywords at the end of the text' do | ||||
|         Glitch::KeywordMute.create!(account: alice, keyword: 'take') | ||||
| 
 | ||||
|         expect(matcher =~ 'This is a hot take').to be_truthy | ||||
|       end | ||||
| 
 | ||||
|       it 'matches if at least one keyword case-insensitively matches the text' do | ||||
|         Glitch::KeywordMute.create!(account: alice, keyword: 'hot') | ||||
| 
 | ||||
|         expect(matcher =~ 'This is a HOT take').to be_truthy | ||||
|       end | ||||
| 
 | ||||
|       it 'matches keywords surrounded by non-alphanumeric ornamentation' do | ||||
|         Glitch::KeywordMute.create!(account: alice, keyword: 'hot') | ||||
| 
 | ||||
|         expect(matcher =~ '(hot take)').to be_truthy | ||||
|       end | ||||
| 
 | ||||
|       it 'escapes metacharacters in keywords' do | ||||
|         Glitch::KeywordMute.create!(account: alice, keyword: '(hot take)') | ||||
| 
 | ||||
|         expect(matcher =~ '(hot take)').to be_truthy | ||||
|       end | ||||
| 
 | ||||
|       it 'uses case-folding rules appropriate for more than just English' do | ||||
|         Glitch::KeywordMute.create!(account: alice, keyword: 'großeltern') | ||||
| 
 | ||||
|         expect(matcher =~ 'besuch der grosseltern').to be_truthy | ||||
|       end | ||||
| 
 | ||||
|       it 'matches keywords that are composed of multiple words' do | ||||
|         Glitch::KeywordMute.create!(account: alice, keyword: 'a shiitake') | ||||
| 
 | ||||
|         expect(matcher =~ 'This is a shiitake').to be_truthy | ||||
|         expect(matcher =~ 'This is shiitake').to_not be_truthy | ||||
|       end | ||||
|     end | ||||
|   end | ||||
| end | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user