mastodon/app/services/bulk_import_service.rb

186 lines
4.8 KiB
Ruby

# frozen_string_literal: true
class BulkImportService < BaseService
def call(import)
@import = import
@account = @import.account
case @import.type.to_sym
when :following
import_follows!
when :blocking
import_blocks!
when :muting
import_mutes!
when :domain_blocking
import_domain_blocks!
when :bookmarks
import_bookmarks!
when :lists
import_lists!
end
@import.update!(state: :finished, finished_at: Time.now.utc) if @import.processed_items == @import.total_items
rescue
@import.update!(state: :finished, finished_at: Time.now.utc)
raise
end
private
def extract_rows_by_acct
local_domain_suffix = "@#{Rails.configuration.x.local_domain}"
@import.rows.to_a.index_by { |row| row.data['acct'].delete_suffix(local_domain_suffix) }
end
def import_follows!
rows_by_acct = extract_rows_by_acct
if @import.overwrite?
@account.following.reorder(nil).find_each do |followee|
row = rows_by_acct.delete(followee.acct)
if row.nil?
UnfollowService.new.call(@account, followee)
else
row.destroy
@import.processed_items += 1
@import.imported_items += 1
# Since we're updating the settings of an existing relationship, we can safely call
# FollowService directly
FollowService.new.call(@account, followee, reblogs: row.data['show_reblogs'], notify: row.data['notify'], languages: row.data['languages'])
end
end
# Save pending infos due to `overwrite?` handling
@import.save!
end
Import::RowWorker.push_bulk(rows_by_acct.values) do |row|
[row.id]
end
end
def import_blocks!
rows_by_acct = extract_rows_by_acct
if @import.overwrite?
@account.blocking.reorder(nil).find_each do |blocked_account|
row = rows_by_acct.delete(blocked_account.acct)
if row.nil?
UnblockService.new.call(@account, blocked_account)
else
row.destroy
@import.processed_items += 1
@import.imported_items += 1
BlockService.new.call(@account, blocked_account)
end
end
# Save pending infos due to `overwrite?` handling
@import.save!
end
Import::RowWorker.push_bulk(rows_by_acct.values) do |row|
[row.id]
end
end
def import_mutes!
rows_by_acct = extract_rows_by_acct
if @import.overwrite?
@account.muting.reorder(nil).find_each do |muted_account|
row = rows_by_acct.delete(muted_account.acct)
if row.nil?
UnmuteService.new.call(@account, muted_account)
else
row.destroy
@import.processed_items += 1
@import.imported_items += 1
MuteService.new.call(@account, muted_account, notifications: row.data['hide_notifications'])
end
end
# Save pending infos due to `overwrite?` handling
@import.save!
end
Import::RowWorker.push_bulk(rows_by_acct.values) do |row|
[row.id]
end
end
def import_domain_blocks!
domains = @import.rows.map { |row| row.data['domain'] }
if @import.overwrite?
@account.domain_blocks.find_each do |domain_block|
domain = domains.delete(domain_block)
@account.unblock_domain!(domain_block.domain) if domain.nil?
end
end
@import.rows.delete_all
domains.each { |domain| @account.block_domain!(domain) }
@import.update!(processed_items: @import.total_items, imported_items: @import.total_items)
AfterAccountDomainBlockWorker.push_bulk(domains) do |domain|
[@account.id, domain]
end
end
def import_bookmarks!
rows_by_uri = @import.rows.index_by { |row| row.data['uri'] }
if @import.overwrite?
@account.bookmarks.includes(:status).find_each do |bookmark|
row = rows_by_uri.delete(ActivityPub::TagManager.instance.uri_for(bookmark.status))
if row.nil?
bookmark.destroy!
else
row.destroy
@import.processed_items += 1
@import.imported_items += 1
end
end
# Save pending infos due to `overwrite?` handling
@import.save!
end
Import::RowWorker.push_bulk(rows_by_uri.values) do |row|
[row.id]
end
end
def import_lists!
rows = @import.rows.to_a
included_lists = rows.map { |row| row.data['list_name'] }.uniq
if @import.overwrite?
@account.owned_lists.where.not(title: included_lists).destroy_all
# As list membership changes do not retroactively change timeline
# contents, simplify things by just clearing everything
@account.owned_lists.find_each do |list|
list.list_accounts.destroy_all
end
end
included_lists.each do |title|
@account.owned_lists.find_or_create_by!(title: title)
end
Import::RowWorker.push_bulk(rows) do |row|
[row.id]
end
end
end