@ -0,0 +1,98 @@ | |||
# frozen_string_literal: true | |||
class RelationshipsController < ApplicationController | |||
layout 'admin' | |||
before_action :authenticate_user! | |||
before_action :set_accounts, only: :show | |||
before_action :set_body_classes | |||
helper_method :following_relationship?, :followed_by_relationship?, :mutual_relationship? | |||
def show | |||
@form = Form::AccountBatch.new | |||
end | |||
def update | |||
@form = Form::AccountBatch.new(form_account_batch_params.merge(current_account: current_account, action: action_from_button)) | |||
@form.save | |||
rescue ActionController::ParameterMissing | |||
# Do nothing | |||
ensure | |||
redirect_to relationships_path(current_params) | |||
end | |||
private | |||
def set_accounts | |||
@accounts = relationships_scope.page(params[:page]).per(40) | |||
end | |||
def relationships_scope | |||
scope = begin | |||
if following_relationship? | |||
current_account.following.includes(:account_stat) | |||
else | |||
current_account.followers.includes(:account_stat) | |||
end | |||
end | |||
scope.merge!(Follow.recent) | |||
scope.merge!(mutual_relationship_scope) if mutual_relationship? | |||
scope.merge!(abandoned_account_scope) if params[:status] == 'abandoned' | |||
scope.merge!(active_account_scope) if params[:status] == 'active' | |||
scope.merge!(by_domain_scope) if params[:by_domain].present? | |||
scope | |||
end | |||
def mutual_relationship_scope | |||
Account.where(id: current_account.following) | |||
end | |||
def abandoned_account_scope | |||
Account.where.not(moved_to_account_id: nil) | |||
end | |||
def active_account_scope | |||
Account.where(moved_to_account_id: nil) | |||
end | |||
def by_domain_scope | |||
Account.where(domain: params[:by_domain]) | |||
end | |||
def form_account_batch_params | |||
params.require(:form_account_batch).permit(:action, account_ids: []) | |||
end | |||
def following_relationship? | |||
params[:relationship].blank? || params[:relationship] == 'following' | |||
end | |||
def mutual_relationship? | |||
params[:relationship] == 'mutual' | |||
end | |||
def followed_by_relationship? | |||
params[:relationship] == 'followed_by' | |||
end | |||
def current_params | |||
params.slice(:page, :status, :relationship, :by_domain).permit(:page, :status, :relationship, :by_domain) | |||
end | |||
def action_from_button | |||
if params[:unfollow] | |||
'unfollow' | |||
elsif params[:remove_from_followers] | |||
'remove_from_followers' | |||
elsif params[:block_domains] | |||
'block_domains' | |||
end | |||
end | |||
def set_body_classes | |||
@body_classes = 'admin' | |||
end | |||
end |
@ -1,28 +0,0 @@ | |||
# frozen_string_literal: true | |||
class Settings::FollowerDomainsController < Settings::BaseController | |||
layout 'admin' | |||
before_action :authenticate_user! | |||
def show | |||
@account = current_account | |||
@domains = current_account.followers.reorder(Arel.sql('MIN(follows.id) DESC')).group('accounts.domain').select('accounts.domain, count(accounts.id) as accounts_from_domain').page(params[:page]).per(10) | |||
end | |||
def update | |||
domains = bulk_params[:select] || [] | |||
AfterAccountDomainBlockWorker.push_bulk(domains) do |domain| | |||
[current_account.id, domain] | |||
end | |||
redirect_to settings_follower_domains_path, notice: I18n.t('followers.success', count: domains.size) | |||
end | |||
private | |||
def bulk_params | |||
params.permit(select: []) | |||
end | |||
end |
@ -0,0 +1,60 @@ | |||
# frozen_string_literal: true | |||
class Form::AccountBatch | |||
include ActiveModel::Model | |||
attr_accessor :account_ids, :action, :current_account | |||
def save | |||
case action | |||
when 'unfollow' | |||
unfollow! | |||
when 'remove_from_followers' | |||
remove_from_followers! | |||
when 'block_domains' | |||
block_domains! | |||
end | |||
end | |||
private | |||
def unfollow! | |||
accounts.find_each do |target_account| | |||
UnfollowService.new.call(current_account, target_account) | |||
end | |||
end | |||
def remove_from_followers! | |||
current_account.passive_relationships.where(account_id: account_ids).find_each do |follow| | |||
reject_follow!(follow) | |||
end | |||
end | |||
def block_domains! | |||
AfterAccountDomainBlockWorker.push_bulk(account_domains) do |domain| | |||
[current_account.id, domain] | |||
end | |||
end | |||
def account_domains | |||
accounts.pluck(Arel.sql('distinct domain')).compact | |||
end | |||
def accounts | |||
Account.where(id: account_ids) | |||
end | |||
def reject_follow!(follow) | |||
follow.destroy | |||
return unless follow.account.activitypub? | |||
json = ActiveModelSerializers::SerializableResource.new( | |||
follow, | |||
serializer: ActivityPub::RejectFollowSerializer, | |||
adapter: ActivityPub::Adapter | |||
).to_json | |||
ActivityPub::DeliveryWorker.perform_async(json, current_account.id, follow.account.inbox_url) | |||
end | |||
end |
@ -0,0 +1,20 @@ | |||
.batch-table__row | |||
%label.batch-table__row__select.batch-table__row__select--aligned.batch-checkbox | |||
= f.check_box :account_ids, { multiple: true, include_hidden: false }, account.id | |||
.batch-table__row__content.batch-table__row__content--unpadded | |||
%table.accounts-table | |||
%tbody | |||
%tr | |||
%td= account_link_to account | |||
%td.accounts-table__count.optional | |||
= number_to_human account.statuses_count, strip_insignificant_zeros: true | |||
%small= t('accounts.posts', count: account.statuses_count).downcase | |||
%td.accounts-table__count.optional | |||
= number_to_human account.followers_count, strip_insignificant_zeros: true | |||
%small= t('accounts.followers', count: account.followers_count).downcase | |||
%td.accounts-table__count | |||
- if account.last_status_at.present? | |||
%time.time-ago{ datetime: account.last_status_at.iso8601, title: l(account.last_status_at) }= l account.last_status_at | |||
- else | |||
\- | |||
%small= t('accounts.last_active') |
@ -0,0 +1,43 @@ | |||
- content_for :page_title do | |||
= t('settings.relationships') | |||
- content_for :header_tags do | |||
= javascript_pack_tag 'admin', integrity: true, async: true, crossorigin: 'anonymous' | |||
.filters | |||
.filter-subset | |||
%strong= t 'relationships.relationship' | |||
%ul | |||
%li= filter_link_to t('accounts.following', count: current_account.following_count), relationship: nil | |||
%li= filter_link_to t('accounts.followers', count: current_account.followers_count), relationship: 'followed_by' | |||
%li= filter_link_to t('relationships.mutual'), relationship: 'mutual' | |||
.filter-subset | |||
%strong= t 'relationships.status' | |||
%ul | |||
%li= filter_link_to t('generic.all'), status: nil | |||
%li= filter_link_to t('relationships.active'), status: 'active' | |||
%li= filter_link_to t('relationships.abandoned'), status: 'abandoned' | |||
= form_for(@form, url: relationships_path, method: :patch) do |f| | |||
= hidden_field_tag :page, params[:page] || 1 | |||
= hidden_field_tag :relationship, params[:relationship] | |||
= hidden_field_tag :status, params[:status] | |||
.batch-table | |||
.batch-table__toolbar | |||
%label.batch-table__toolbar__select.batch-checkbox-all | |||
= check_box_tag :batch_checkbox_all, nil, false | |||
.batch-table__toolbar__actions | |||
= f.button safe_join([fa_icon('user-times'), t('relationships.remove_selected_follows')]), name: :unfollow, class: 'table-action-link', type: :submit, data: { confirm: t('admin.reports.are_you_sure') } unless followed_by_relationship? | |||
= f.button safe_join([fa_icon('trash'), t('relationships.remove_selected_followers')]), name: :remove_from_followers, class: 'table-action-link', type: :submit, data: { confirm: t('admin.reports.are_you_sure') } unless following_relationship? | |||
= f.button safe_join([fa_icon('trash'), t('relationships.remove_selected_domains')]), name: :block_domains, class: 'table-action-link', type: :submit, data: { confirm: t('admin.reports.are_you_sure') } if followed_by_relationship? | |||
.batch-table__body | |||
- if @accounts.empty? | |||
= nothing_here 'nothing-here--under-tabs' | |||
- else | |||
= render partial: 'account', collection: @accounts, locals: { f: f } | |||
= paginate @accounts |
@ -1,34 +0,0 @@ | |||
- content_for :page_title do | |||
= t('settings.followers') | |||
= form_tag settings_follower_domains_path, method: :patch, class: 'table-form' do | |||
- unless @account.locked? | |||
.warning | |||
%strong | |||
= fa_icon('warning') | |||
= t('followers.unlocked_warning_title') | |||
= t('followers.unlocked_warning_html', lock_link: link_to(t('followers.lock_link'), settings_profile_url)) | |||
%p= t('followers.explanation_html') | |||
%p= t('followers.true_privacy_html') | |||
.table-wrapper | |||
%table.table | |||
%thead | |||
%tr | |||
%th | |||
%th= t('followers.domain') | |||
%th= t('followers.followers_count') | |||
%tbody | |||
- @domains.each do |domain| | |||
%tr | |||
%td | |||
= check_box_tag 'select[]', domain.domain, false, disabled: !@account.locked? unless domain.domain.nil? | |||
%td | |||
%samp= domain.domain.presence || Rails.configuration.x.local_domain | |||
%td= number_with_delimiter domain.accounts_from_domain | |||
.action-pagination | |||
.actions | |||
= button_tag t('followers.purge'), type: :submit, class: 'button', disabled: !@account.locked? | |||
= paginate @domains |