filter for only public and unlisted posts

This commit is contained in:
sneakers-the-rat 2025-05-02 23:32:34 -07:00
parent e489b9e34d
commit 849c0500b0
No known key found for this signature in database
GPG Key ID: 6DCB96EF1E4D232D
2 changed files with 78 additions and 1 deletions

View File

@ -3,7 +3,7 @@
class ActivityPub::AccountBackfillService < BaseService
include JsonLdHelper
ENABLED = (ENV['ACCOUNT_BACKFILL_ENABLED'] || true).to_bool
ENABLED = ENV['ACCOUNT_BACKFILL_ENABLED'].nil? || ENV['ACCOUNT_BACKFILL_ENABLED'] == 'true'
MAX_STATUSES = (ENV['ACCOUNT_BACKFILL_MAX_STATUSES'] || 500).to_i
MAX_PAGES = (ENV['ACCOUNT_BACKFILL_MAX_PAGES'] || 100).to_i
@ -14,6 +14,7 @@ class ActivityPub::AccountBackfillService < BaseService
return if @account.nil? || @account.outbox_url.nil?
@items, = collection_items(@account.outbox_url, max_items: MAX_STATUSES, max_pages: MAX_PAGES, on_behalf_of: on_behalf_of)
@items = filter_items(@items)
return if @items.nil?
on_behalf_of_id = on_behalf_of&.id
@ -30,4 +31,23 @@ class ActivityPub::AccountBackfillService < BaseService
@items
end
private
# Reject any non-public statuses.
# Since our request may have been signed on behalf of the follower,
# we may have received followers-only statuses.
#
# Formally, a followers-only status is addressed to the account's followers collection.
# We were not in that collection at the time that the post was made,
# so followers-only statuses fetched by backfilling are not addressed to us.
# Public and unlisted statuses are send to the activitystreams "Public" entity.
# We are part of the public, so those posts *are* addressed to us.
#
# @param items [Array<Hash>]
# @return [Array<Hash>]
def filter_items(items)
allowed = [:public, :unlisted]
items.filter { |item| item.is_a?(String) || allowed.include?(ActivityPub::Parser::StatusParser.new(item).visibility) }
end
end

View File

@ -5,11 +5,16 @@ require 'rails_helper'
RSpec.describe ActivityPub::AccountBackfillService do
subject { described_class.new }
before do
stub_const('ActivityPub::AccountBackfillService::ENABLED', true)
end
let!(:account) { Fabricate(:account, domain: 'other.com', outbox_url: 'http://other.com/alice/outbox') }
let!(:outbox) do
{
'@context': 'https://www.w3.org/ns/activitystreams',
id: 'http://other.com/alice/outbox',
type: 'OrderedCollection',
first: 'http://other.com/alice/outbox?page=true',
@ -21,6 +26,8 @@ RSpec.describe ActivityPub::AccountBackfillService do
{
'@context': 'https://www.w3.org/ns/activitystreams',
id: 'https://other.com/alice/1234',
to: ['https://www.w3.org/ns/activitystreams#Public'],
cc: ['https://other.com/alice/followers'],
type: 'Note',
content: 'Lorem ipsum',
attributedTo: 'http://other.com/alice',
@ -51,5 +58,55 @@ RSpec.describe ActivityPub::AccountBackfillService do
expect(got_items[1]).to eq(items[1])
expect(FetchReplyWorker).to have_received(:push_bulk).with([items[0].stringify_keys, items[1]])
end
context 'with followers-only and private statuses' do
let!(:items) do
[
{
'@context': 'https://www.w3.org/ns/activitystreams',
id: 'https://other.com/alice/public',
type: 'Note',
to: ['https://www.w3.org/ns/activitystreams#Public'],
cc: ['https://other.com/alice/followers'],
content: 'Lorem ipsum',
attributedTo: 'http://other.com/alice',
},
{
'@context': 'https://www.w3.org/ns/activitystreams',
id: 'https://other.com/alice/unlisted',
to: ['https://other.com/alice/followers'],
cc: ['https://www.w3.org/ns/activitystreams#Public'],
type: 'Note',
content: 'Lorem ipsum',
attributedTo: 'http://other.com/alice',
},
{
'@context': 'https://www.w3.org/ns/activitystreams',
id: 'https://other.com/alice/followers-only',
to: ['https://other.com/alice/followers'],
type: 'Note',
content: 'Lorem ipsum',
attributedTo: 'http://other.com/alice',
},
{
'@context': 'https://www.w3.org/ns/activitystreams',
id: 'https://other.com/alice/dm',
to: ['https://other.com/alice/followers'],
type: 'Note',
content: 'Lorem ipsum',
attributedTo: 'http://other.com/alice',
},
]
end
it 'only processes public and unlisted statuses' do
allow(FetchReplyWorker).to receive(:push_bulk)
got_items = subject.call(account)
expect(got_items.length).to eq(2)
expect(got_items[0].deep_symbolize_keys).to eq(items[0])
expect(got_items[1].deep_symbolize_keys).to eq(items[1])
expect(FetchReplyWorker).to have_received(:push_bulk).with([items[0].stringify_keys, items[1].stringify_keys])
end
end
end
end