Merge branch 'main' into glitch-soc/merge-upstream
Conflicts: - `app/models/status.rb`: Upstream updated media and edit-related code textually close to glitch-soc additions (local-only and content-type). Ported upstream changes. - `app/models/status_edit.rb`: Upstream changes textually close to glitch-soc additions (content-type). Ported upstream changes. - `app/serializers/activitypub/note_serializer.rb`: Upstream changed how media attachments are handled. Not really a conflict, but textually close to glitch-soc additions (directMessage attribute). Ported upstream changes. - `app/services/remove_status_service.rb`: Upstream changed how media attachments are handled. Not really a conflict, but textually close to glitch-soc additions (DM timeline). Ported upstream changes. - `app/services/update_status_service.rb`: Upstream fixed an issue with language selection. Not really a conflict, but textually close to glitch-soc additions (content-type). Ported upstream changes. - `db/schema.rb`: Upstream added columns to the `status_edits` table, the conflict is because of an additional column (`content-type`) in glitch-soc. Ported upstream changes. - `package.json`: Upstream dependency (express) textually adjacent to a glitch-soc-specific one (favico.js) got updated. Updated it as well.
This commit is contained in:
@ -3,31 +3,31 @@
|
||||
#
|
||||
# Table name: statuses
|
||||
#
|
||||
# id :bigint(8) not null, primary key
|
||||
# uri :string
|
||||
# text :text default(""), not null
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# in_reply_to_id :bigint(8)
|
||||
# reblog_of_id :bigint(8)
|
||||
# url :string
|
||||
# sensitive :boolean default(FALSE), not null
|
||||
# visibility :integer default("public"), not null
|
||||
# spoiler_text :text default(""), not null
|
||||
# reply :boolean default(FALSE), not null
|
||||
# language :string
|
||||
# conversation_id :bigint(8)
|
||||
# local :boolean
|
||||
# account_id :bigint(8) not null
|
||||
# application_id :bigint(8)
|
||||
# in_reply_to_account_id :bigint(8)
|
||||
# local_only :boolean
|
||||
# full_status_text :text default(""), not null
|
||||
# poll_id :bigint(8)
|
||||
# content_type :string
|
||||
# deleted_at :datetime
|
||||
# edited_at :datetime
|
||||
# trendable :boolean
|
||||
# id :bigint(8) not null, primary key
|
||||
# uri :string
|
||||
# text :text default(""), not null
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# in_reply_to_id :bigint(8)
|
||||
# reblog_of_id :bigint(8)
|
||||
# url :string
|
||||
# sensitive :boolean default(FALSE), not null
|
||||
# visibility :integer default("public"), not null
|
||||
# spoiler_text :text default(""), not null
|
||||
# reply :boolean default(FALSE), not null
|
||||
# language :string
|
||||
# conversation_id :bigint(8)
|
||||
# local :boolean
|
||||
# account_id :bigint(8) not null
|
||||
# application_id :bigint(8)
|
||||
# in_reply_to_account_id :bigint(8)
|
||||
# local_only :boolean
|
||||
# poll_id :bigint(8)
|
||||
# content_type :string
|
||||
# deleted_at :datetime
|
||||
# edited_at :datetime
|
||||
# trendable :boolean
|
||||
# ordered_media_attachment_ids :bigint(8) is an Array
|
||||
#
|
||||
|
||||
class Status < ApplicationRecord
|
||||
@ -217,14 +217,18 @@ class Status < ApplicationRecord
|
||||
public_visibility? || unlisted_visibility?
|
||||
end
|
||||
|
||||
def snapshot!(media_attachments_changed: false, account_id: nil, at_time: nil)
|
||||
def snapshot!(account_id: nil, at_time: nil, rate_limit: true)
|
||||
edits.create!(
|
||||
text: text,
|
||||
spoiler_text: spoiler_text,
|
||||
media_attachments_changed: media_attachments_changed,
|
||||
sensitive: sensitive,
|
||||
ordered_media_attachment_ids: ordered_media_attachment_ids || media_attachments.pluck(:id),
|
||||
media_descriptions: ordered_media_attachments.map(&:description),
|
||||
poll_options: preloadable_poll&.options,
|
||||
account_id: account_id || self.account_id,
|
||||
content_type: content_type,
|
||||
created_at: at_time || edited_at
|
||||
created_at: at_time || edited_at,
|
||||
rate_limit: rate_limit
|
||||
)
|
||||
end
|
||||
|
||||
@ -235,7 +239,7 @@ class Status < ApplicationRecord
|
||||
alias sign? distributable?
|
||||
|
||||
def with_media?
|
||||
media_attachments.any?
|
||||
ordered_media_attachments.any?
|
||||
end
|
||||
|
||||
def with_preview_card?
|
||||
@ -259,6 +263,15 @@ class Status < ApplicationRecord
|
||||
@emojis = CustomEmoji.from_text(fields.join(' '), account.domain)
|
||||
end
|
||||
|
||||
def ordered_media_attachments
|
||||
if ordered_media_attachment_ids.nil?
|
||||
media_attachments
|
||||
else
|
||||
map = media_attachments.index_by(&:id)
|
||||
ordered_media_attachment_ids.map { |media_attachment_id| map[media_attachment_id] }
|
||||
end
|
||||
end
|
||||
|
||||
def replies_count
|
||||
status_stat&.replies_count || 0
|
||||
end
|
||||
@ -428,6 +441,63 @@ class Status < ApplicationRecord
|
||||
super || build_status_stat
|
||||
end
|
||||
|
||||
# Hack to use a "INSERT INTO ... SELECT ..." query instead of "INSERT INTO ... VALUES ..." query
|
||||
def self._insert_record(values)
|
||||
if values.is_a?(Hash) && values['reblog_of_id'].present?
|
||||
primary_key = self.primary_key
|
||||
primary_key_value = nil
|
||||
|
||||
if primary_key
|
||||
primary_key_value = values[primary_key]
|
||||
|
||||
if !primary_key_value && prefetch_primary_key?
|
||||
primary_key_value = next_sequence_value
|
||||
values[primary_key] = primary_key_value
|
||||
end
|
||||
end
|
||||
|
||||
# The following line is where we differ from stock ActiveRecord implementation
|
||||
im = _compile_reblog_insert(values)
|
||||
|
||||
# Since we are using SELECT instead of VALUES, a non-error `nil` return is possible.
|
||||
# For our purposes, it's equivalent to a foreign key constraint violation
|
||||
result = connection.insert(im, "#{self} Create", primary_key || false, primary_key_value)
|
||||
raise ActiveRecord::InvalidForeignKey, "(reblog_of_id)=(#{values['reblog_of_id']}) is not present in table \"statuses\"" if result.nil?
|
||||
|
||||
result
|
||||
else
|
||||
super
|
||||
end
|
||||
end
|
||||
|
||||
def self._compile_reblog_insert(values)
|
||||
# This is somewhat equivalent to the following code of ActiveRecord::Persistence:
|
||||
# `arel_table.compile_insert(_substitute_values(values))`
|
||||
# The main difference is that we use a `SELECT` instead of a `VALUES` clause,
|
||||
# which means we have to build the `SELECT` clause ourselves and do a bit more
|
||||
# manual work.
|
||||
|
||||
# Instead of using Arel::InsertManager#values, we are going to use Arel::InsertManager#select
|
||||
im = Arel::InsertManager.new
|
||||
im.into(arel_table)
|
||||
|
||||
binds = []
|
||||
reblog_bind = nil
|
||||
values.each do |name, value|
|
||||
attr = arel_table[name]
|
||||
bind = predicate_builder.build_bind_attribute(attr.name, value)
|
||||
|
||||
im.columns << attr
|
||||
binds << bind
|
||||
|
||||
reblog_bind = bind if name == 'reblog_of_id'
|
||||
end
|
||||
|
||||
im.select(arel_table.where(arel_table[:id].eq(reblog_bind)).where(arel_table[:deleted_at].eq(nil)).project(*binds))
|
||||
|
||||
im
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def update_status_stat!(attrs)
|
||||
|
Reference in New Issue
Block a user