Add conversation model, <ostatus:conversation /> (#3016)
* Add <ostatus:conversation /> tag to Atom input/output Only uses ref attribute (not href) because href would be the alternate link that's always included also. Creates new conversation for every non-reply status. Carries over conversation for every reply. Keeps remote URIs verbatim, generates local URIs on the fly like the rest of them. * Fix conversation migration * More spec coverage for status before_create * Prevent n+1 query when generating Atom with the new conversations * Improve code style * Remove redundant local variable
This commit is contained in:
parent
b5a9c6b3d2
commit
5abdc77c80
11 changed files with 144 additions and 10 deletions
20
app/models/conversation.rb
Normal file
20
app/models/conversation.rb
Normal file
|
@ -0,0 +1,20 @@
|
|||
# frozen_string_literal: true
|
||||
# == Schema Information
|
||||
#
|
||||
# Table name: conversations
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# uri :string
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
#
|
||||
|
||||
class Conversation < ApplicationRecord
|
||||
validates :uri, uniqueness: true
|
||||
|
||||
has_many :statuses
|
||||
|
||||
def local?
|
||||
uri.nil?
|
||||
end
|
||||
end
|
|
@ -21,6 +21,7 @@
|
|||
# favourites_count :integer default(0), not null
|
||||
# reblogs_count :integer default(0), not null
|
||||
# language :string default("en"), not null
|
||||
# conversation_id :integer
|
||||
#
|
||||
|
||||
class Status < ApplicationRecord
|
||||
|
@ -34,6 +35,7 @@ class Status < ApplicationRecord
|
|||
|
||||
belongs_to :account, inverse_of: :statuses, counter_cache: true, required: true
|
||||
belongs_to :in_reply_to_account, foreign_key: 'in_reply_to_account_id', class_name: 'Account'
|
||||
belongs_to :conversation
|
||||
|
||||
belongs_to :thread, foreign_key: 'in_reply_to_id', class_name: 'Status', inverse_of: :replies
|
||||
belongs_to :reblog, foreign_key: 'reblog_of_id', class_name: 'Status', inverse_of: :reblogs, counter_cache: :reblogs_count
|
||||
|
@ -141,6 +143,11 @@ class Status < ApplicationRecord
|
|||
!sensitive? && media_attachments.any?
|
||||
end
|
||||
|
||||
before_validation :prepare_contents
|
||||
before_create :set_reblog
|
||||
before_create :set_visibility
|
||||
before_create :set_conversation
|
||||
|
||||
class << self
|
||||
def in_allowed_languages(account)
|
||||
where(language: account.allowed_languages)
|
||||
|
@ -242,17 +249,39 @@ class Status < ApplicationRecord
|
|||
end
|
||||
end
|
||||
|
||||
before_validation do
|
||||
private
|
||||
|
||||
def prepare_contents
|
||||
text&.strip!
|
||||
spoiler_text&.strip!
|
||||
|
||||
self.reply = !(in_reply_to_id.nil? && thread.nil?) unless reply
|
||||
self.reblog = reblog.reblog if reblog? && reblog.reblog?
|
||||
self.in_reply_to_account_id = (thread.account_id == account_id && thread.reply? ? thread.in_reply_to_account_id : thread.account_id) if reply? && !thread.nil?
|
||||
self.visibility = (account.locked? ? :private : :public) if visibility.nil?
|
||||
end
|
||||
|
||||
private
|
||||
def set_reblog
|
||||
self.reblog = reblog.reblog if reblog? && reblog.reblog?
|
||||
end
|
||||
|
||||
def set_visibility
|
||||
self.visibility = (account.locked? ? :private : :public) if visibility.nil?
|
||||
end
|
||||
|
||||
def set_conversation
|
||||
self.reply = !(in_reply_to_id.nil? && thread.nil?) unless reply
|
||||
|
||||
if reply? && !thread.nil?
|
||||
self.in_reply_to_account_id = carried_over_reply_to_account_id
|
||||
self.conversation_id = thread.conversation_id if conversation_id.nil?
|
||||
elsif conversation_id.nil?
|
||||
create_conversation
|
||||
end
|
||||
end
|
||||
|
||||
def carried_over_reply_to_account_id
|
||||
if thread.account_id == account_id && thread.reply?
|
||||
thread.in_reply_to_account_id
|
||||
else
|
||||
thread.account_id
|
||||
end
|
||||
end
|
||||
|
||||
def filter_from_context?(status, account)
|
||||
account&.blocking?(status.account_id) || account&.muting?(status.account_id) || (status.account.silenced? && !account&.following?(status.account_id)) || !status.permitted?(account)
|
||||
|
|
|
@ -22,7 +22,7 @@ class StreamEntry < ApplicationRecord
|
|||
|
||||
validates :account, :activity, presence: true
|
||||
|
||||
STATUS_INCLUDES = [:account, :stream_entry, :media_attachments, :tags, mentions: :account, reblog: [:stream_entry, :account, :media_attachments, :tags, mentions: :account], thread: [:stream_entry, :account]].freeze
|
||||
STATUS_INCLUDES = [:account, :stream_entry, :conversation, :media_attachments, :tags, mentions: :account, reblog: [:stream_entry, :account, :conversation, :media_attachments, :tags, mentions: :account], thread: [:stream_entry, :account]].freeze
|
||||
|
||||
default_scope { where(activity_type: 'Status') }
|
||||
scope :with_includes, -> { includes(:account, status: STATUS_INCLUDES) }
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue