Add backend support for storing remote actors profile pic and header descriptions (#37634)

pull/35369/head^2
Claire 4 weeks ago committed by GitHub
parent 1ae6b52c47
commit 6af4696c70
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -67,3 +67,4 @@ The following table summarizes those limits.
| Account `attributionDomains` | 256 | List will be truncated |
| Account aliases (actor `alsoKnownAs`) | 256 | List will be truncated |
| Custom emoji shortcode (`Emoji` `name`) | 2048 | Emoji will be rejected |
| Media and avatar/header descriptions (`name`/`summary`) | 1500 | Description will be truncated |

@ -9,6 +9,7 @@
# also_known_as :string is an Array
# attribution_domains :string default([]), is an Array
# avatar_content_type :string
# avatar_description :string default(""), not null
# avatar_file_name :string
# avatar_file_size :integer
# avatar_remote_url :string
@ -23,6 +24,7 @@
# followers_url :string default(""), not null
# following_url :string default(""), not null
# header_content_type :string
# header_description :string default(""), not null
# header_file_name :string
# header_file_size :integer
# header_remote_url :string default(""), not null

@ -24,6 +24,8 @@ module Account::Avatar
validates_attachment_content_type :avatar, content_type: AVATAR_IMAGE_MIME_TYPES
validates_attachment_size :avatar, less_than: AVATAR_LIMIT
remotable_attachment :avatar, AVATAR_LIMIT, suppress_errors: false
validates :avatar_description, length: { maximum: MediaAttachment::MAX_DESCRIPTION_LENGTH }
end
def avatar_original_url

@ -25,6 +25,8 @@ module Account::Header
validates_attachment_content_type :header, content_type: HEADER_IMAGE_MIME_TYPES
validates_attachment_size :header, less_than: HEADER_LIMIT
remotable_attachment :header, HEADER_LIMIT, suppress_errors: false
validates :header_description, length: { maximum: MediaAttachment::MAX_DESCRIPTION_LENGTH }
end
def header_original_url

@ -7,7 +7,7 @@ class REST::AccountSerializer < ActiveModel::Serializer
# Please update `app/javascript/mastodon/api_types/accounts.ts` when making changes to the attributes
attributes :id, :username, :acct, :display_name, :locked, :bot, :discoverable, :indexable, :group, :created_at,
:note, :url, :uri, :avatar, :avatar_static, :header, :header_static,
:note, :url, :uri, :avatar, :avatar_static, :avatar_description, :header, :header_static, :header_description,
:followers_count, :following_count, :statuses_count, :last_status_at, :hide_collections
has_one :moved_to_account, key: :moved, serializer: REST::AccountSerializer, if: :moved_and_not_nested?

@ -142,14 +142,18 @@ class ActivityPub::ProcessAccountService < BaseService
def set_fetchable_attributes!
begin
@account.avatar_remote_url = image_url('icon') || '' unless skip_download?
avatar_url, avatar_description = image_url_and_description('icon')
@account.avatar_remote_url = avatar_url || '' unless skip_download?
@account.avatar = nil if @account.avatar_remote_url.blank?
@account.avatar_description = avatar_description || ''
rescue Mastodon::UnexpectedResponseError, *Mastodon::HTTP_CONNECTION_ERRORS
RedownloadAvatarWorker.perform_in(rand(30..600).seconds, @account.id)
end
begin
@account.header_remote_url = image_url('image') || '' unless skip_download?
header_url, header_description = image_url_and_description('image')
@account.header_remote_url = header_url || '' unless skip_download?
@account.header = nil if @account.header_remote_url.blank?
@account.header_description = header_description || ''
rescue Mastodon::UnexpectedResponseError, *Mastodon::HTTP_CONNECTION_ERRORS
RedownloadHeaderWorker.perform_in(rand(30..600).seconds, @account.id)
end
@ -214,7 +218,7 @@ class ActivityPub::ProcessAccountService < BaseService
end
end
def image_url(key)
def image_url_and_description(key)
value = first_of_value(@json[key])
return if value.nil?
@ -224,9 +228,21 @@ class ActivityPub::ProcessAccountService < BaseService
return if value.nil?
end
value = first_of_value(value['url']) if value.is_a?(Hash) && value['type'] == 'Image'
value = value['href'] if value.is_a?(Hash)
value if value.is_a?(String)
if value.is_a?(Hash) && value['type'] == 'Image'
url = first_of_value(value['url'])
url = url['href'] if url.is_a?(Hash)
description = value['summary'].presence || value['name'].presence
description = description.strip[0...MediaAttachment::MAX_DESCRIPTION_LENGTH] if description.present?
else
url = value
end
url = url['href'] if url.is_a?(Hash)
url = nil unless url.is_a?(String)
description = nil unless description.is_a?(String)
[url, description]
end
def public_key

@ -0,0 +1,7 @@
# frozen_string_literal: true
class AddAvatarDescriptionToAccounts < ActiveRecord::Migration[8.0]
def change
add_column :accounts, :avatar_description, :string, null: false, default: ''
end
end

@ -0,0 +1,7 @@
# frozen_string_literal: true
class AddHeaderDescriptionToAccounts < ActiveRecord::Migration[8.0]
def change
add_column :accounts, :header_description, :string, null: false, default: ''
end
end

@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema[8.0].define(version: 2026_01_19_153538) do
ActiveRecord::Schema[8.0].define(version: 2026_01_27_141820) do
# These are extensions that must be enabled in order to support this database
enable_extension "pg_catalog.plpgsql"
@ -201,6 +201,8 @@ ActiveRecord::Schema[8.0].define(version: 2026_01_19_153538) do
t.string "following_url", default: "", null: false
t.integer "id_scheme", default: 1
t.integer "feature_approval_policy", default: 0, null: false
t.string "avatar_description", default: "", null: false
t.string "header_description", default: "", null: false
t.index "(((setweight(to_tsvector('simple'::regconfig, (display_name)::text), 'A'::\"char\") || setweight(to_tsvector('simple'::regconfig, (username)::text), 'B'::\"char\")) || setweight(to_tsvector('simple'::regconfig, (COALESCE(domain, ''::character varying))::text), 'C'::\"char\")))", name: "search_index", using: :gin
t.index "lower((username)::text), COALESCE(lower((domain)::text), ''::text)", name: "index_accounts_on_username_and_domain_lower", unique: true
t.index ["domain", "id"], name: "index_accounts_on_domain_and_id"

Loading…
Cancel
Save