about summary refs log tree commit diff
path: root/app/models
diff options
context:
space:
mode:
Diffstat (limited to 'app/models')
-rw-r--r--app/models/custom_emoji.rb1
-rw-r--r--app/models/glitch.rb7
-rw-r--r--app/models/glitch/keyword_mute.rb66
-rw-r--r--app/models/status.rb8
4 files changed, 82 insertions, 0 deletions
diff --git a/app/models/custom_emoji.rb b/app/models/custom_emoji.rb
index 65d9840d5..28b6a2b0b 100644
--- a/app/models/custom_emoji.rb
+++ b/app/models/custom_emoji.rb
@@ -15,6 +15,7 @@
 #  disabled           :boolean          default(FALSE), not null
 #  uri                :string
 #  image_remote_url   :string
+#  visible_in_picker  :boolean          default(TRUE), not null
 #
 
 class CustomEmoji < ApplicationRecord
diff --git a/app/models/glitch.rb b/app/models/glitch.rb
new file mode 100644
index 000000000..0e497babc
--- /dev/null
+++ b/app/models/glitch.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+module Glitch
+  def self.table_name_prefix
+    'glitch_'
+  end
+end
diff --git a/app/models/glitch/keyword_mute.rb b/app/models/glitch/keyword_mute.rb
new file mode 100644
index 000000000..73de4d4b7
--- /dev/null
+++ b/app/models/glitch/keyword_mute.rb
@@ -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
diff --git a/app/models/status.rb b/app/models/status.rb
index 30d53f298..d78a921b5 100644
--- a/app/models/status.rb
+++ b/app/models/status.rb
@@ -154,6 +154,14 @@ class Status < ApplicationRecord
       where(account: [account] + account.following).where(visibility: [:public, :unlisted, :private])
     end
 
+    def as_direct_timeline(account)
+      query = joins("LEFT OUTER JOIN mentions ON statuses.id = mentions.status_id AND mentions.account_id = #{account.id}")
+              .where("mentions.account_id = #{account.id} OR statuses.account_id = #{account.id}")
+              .where(visibility: [:direct])
+
+      apply_timeline_filters(query, account, false)
+    end
+
     def as_public_timeline(account = nil, local_only = false)
       query = timeline_scope(local_only).without_replies