Add support for preview cards for local posts/accounts

This commit is contained in:
Claire 2024-02-28 17:18:31 +01:00
parent b3d970bdb8
commit 77dd4b3341
9 changed files with 83 additions and 2 deletions

View file

@ -32,6 +32,8 @@
# link_type :integer # link_type :integer
# published_at :datetime # published_at :datetime
# image_description :string default(""), not null # image_description :string default(""), not null
# target_status_id :bigint(8)
# target_account_id :bigint(8)
# #
class PreviewCard < ApplicationRecord class PreviewCard < ApplicationRecord
@ -50,6 +52,9 @@ class PreviewCard < ApplicationRecord
enum :type, { link: 0, photo: 1, video: 2, rich: 3 } enum :type, { link: 0, photo: 1, video: 2, rich: 3 }
enum :link_type, { unknown: 0, article: 1 } enum :link_type, { unknown: 0, article: 1 }
belongs_to :target_status, class_name: 'Status', optional: true, dependent: :destroy
belongs_to :target_account, class_name: 'Account', optional: true, dependent: :destroy
has_many :preview_cards_statuses, dependent: :delete_all, inverse_of: :preview_card has_many :preview_cards_statuses, dependent: :delete_all, inverse_of: :preview_card
has_many :statuses, through: :preview_cards_statuses has_many :statuses, through: :preview_cards_statuses

View file

@ -26,6 +26,7 @@ class FetchLinkCardService < BaseService
with_redis_lock("fetch:#{@original_url}") do with_redis_lock("fetch:#{@original_url}") do
@card = PreviewCard.find_by(url: @url) @card = PreviewCard.find_by(url: @url)
process_url if @card.nil? || @card.updated_at <= 2.weeks.ago || @card.missing_image? process_url if @card.nil? || @card.updated_at <= 2.weeks.ago || @card.missing_image?
attach_local_resource_to_card!
end end
attach_card if @card&.persisted? attach_card if @card&.persisted?
@ -60,6 +61,22 @@ class FetchLinkCardService < BaseService
end end
end end
def attach_local_resource_to_card!
return if @card.nil? || @card.target_account_id.present? || @card.target_status_id.present? || !TagManager.instance.local_url?(@card.url)
recognized_params = Rails.application.routes.recognize_path(@card.url)
return if recognized_params[:action] != 'show'
case recognized_params[:controller]
when 'accounts'
account = Account.find_local(recognized_params[:username])
@card.update!(target_account: account)
when 'statuses'
status = Status.find_by(id: recognized_params[:id])
@card.update!(target_status: status)
end
end
def attach_card def attach_card
with_redis_lock("attach_card:#{@status.id}") do with_redis_lock("attach_card:#{@status.id}") do
return if @status.with_preview_card? return if @status.with_preview_card?
@ -85,7 +102,14 @@ class FetchLinkCardService < BaseService
def bad_url?(uri) def bad_url?(uri)
# Avoid local instance URLs and invalid URLs # Avoid local instance URLs and invalid URLs
uri.host.blank? || TagManager.instance.local_url?(uri.to_s) || !%w(http https).include?(uri.scheme) uri.host.blank? || bad_local_url?(uri.to_s) || !%w(http https).include?(uri.scheme)
end
def bad_local_url?(uri)
return false unless TagManager.instance.local_url?(uri.to_s)
recognized_params = Rails.application.routes.recognize_path(uri)
recognized_params[:action] != 'show' || %w(accounts statuses).exclude?(recognized_params[:controller])
end end
def mention_link?(anchor) def mention_link?(anchor)

View file

@ -0,0 +1,9 @@
# frozen_string_literal: true
class AddTargetStatusIdToPreviewCards < ActiveRecord::Migration[7.1]
disable_ddl_transaction!
def change
add_belongs_to :preview_cards, :target_status, null: true, index: { algorithm: :concurrently, where: 'target_status_id IS NOT NULL' }
end
end

View file

@ -0,0 +1,7 @@
# frozen_string_literal: true
class AddTargetStatusForeignKeyToPreviewCards < ActiveRecord::Migration[7.1]
def change
add_foreign_key :preview_cards, :statuses, column: :target_status_id, on_delete: :cascade, validate: false
end
end

View file

@ -0,0 +1,7 @@
# frozen_string_literal: true
class ValidateTargetStatusForeignKeyOnPreviewCards < ActiveRecord::Migration[7.1]
def change
validate_foreign_key :preview_cards, column: :target_status_id
end
end

View file

@ -0,0 +1,9 @@
# frozen_string_literal: true
class AddTargetAccountIdToPreviewCards < ActiveRecord::Migration[7.1]
disable_ddl_transaction!
def change
add_belongs_to :preview_cards, :target_account, null: true, index: { algorithm: :concurrently, where: 'target_account_id IS NOT NULL' }
end
end

View file

@ -0,0 +1,7 @@
# frozen_string_literal: true
class AddTargetAccountForeignKeyToPreviewCards < ActiveRecord::Migration[7.1]
def change
add_foreign_key :preview_cards, :accounts, column: :target_account_id, on_delete: :cascade, validate: false
end
end

View file

@ -0,0 +1,7 @@
# frozen_string_literal: true
class ValidateTargetAccountForeignKeyOnPreviewCards < ActiveRecord::Migration[7.1]
def change
validate_foreign_key :preview_cards, column: :target_account_id
end
end

View file

@ -10,7 +10,7 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema[7.1].define(version: 2024_03_22_161611) do ActiveRecord::Schema[7.1].define(version: 2024_03_26_161740) do
# These are extensions that must be enabled in order to support this database # These are extensions that must be enabled in order to support this database
enable_extension "plpgsql" enable_extension "plpgsql"
@ -874,6 +874,10 @@ ActiveRecord::Schema[7.1].define(version: 2024_03_22_161611) do
t.integer "link_type" t.integer "link_type"
t.datetime "published_at" t.datetime "published_at"
t.string "image_description", default: "", null: false t.string "image_description", default: "", null: false
t.bigint "target_status_id"
t.bigint "target_account_id"
t.index ["target_account_id"], name: "index_preview_cards_on_target_account_id", where: "(target_account_id IS NOT NULL)"
t.index ["target_status_id"], name: "index_preview_cards_on_target_status_id", where: "(target_status_id IS NOT NULL)"
t.index ["url"], name: "index_preview_cards_on_url", unique: true t.index ["url"], name: "index_preview_cards_on_url", unique: true
end end
@ -1347,6 +1351,8 @@ ActiveRecord::Schema[7.1].define(version: 2024_03_22_161611) do
add_foreign_key "polls", "accounts", on_delete: :cascade add_foreign_key "polls", "accounts", on_delete: :cascade
add_foreign_key "polls", "statuses", on_delete: :cascade add_foreign_key "polls", "statuses", on_delete: :cascade
add_foreign_key "preview_card_trends", "preview_cards", on_delete: :cascade add_foreign_key "preview_card_trends", "preview_cards", on_delete: :cascade
add_foreign_key "preview_cards", "accounts", column: "target_account_id", on_delete: :cascade
add_foreign_key "preview_cards", "statuses", column: "target_status_id", on_delete: :cascade
add_foreign_key "report_notes", "accounts", on_delete: :cascade add_foreign_key "report_notes", "accounts", on_delete: :cascade
add_foreign_key "report_notes", "reports", on_delete: :cascade add_foreign_key "report_notes", "reports", on_delete: :cascade
add_foreign_key "reports", "accounts", column: "action_taken_by_account_id", name: "fk_bca45b75fd", on_delete: :nullify add_foreign_key "reports", "accounts", column: "action_taken_by_account_id", name: "fk_bca45b75fd", on_delete: :nullify