Files
manyfold/app/controllers/follows_controller.rb
T

113 lines
3.9 KiB
Ruby

class FollowsController < ApplicationController
before_action :get_target, except: [:index, :new, :remote_follow, :perform_remote_follow, :follow_remote_actor, :unfollow_remote_actor]
skip_after_action :verify_policy_scoped, only: :index
skip_after_action :verify_authorized, only: [:new, :remote_follow, :perform_remote_follow]
def index
authorize Federails::Following
@followings = current_user&.federails_actor&.follows
@followers = current_user&.federails_actor&.followers
end
# Incoming remote follow
def new
@query = params[:uri]
# Get actor if this is a HTTP or acct URI
if @query.present?
begin
actor_uri = if @query.starts_with?(%r{https?://})
@query
elsif @query.include?("@")
Federails::Actor.find_by_account(@query)&.federated_url # rubocop:disable Rails/DynamicFindBy
else
nil
end
@actor = Federails::Actor.find_or_create_by_federation_url actor_uri if actor_uri # rubocop:disable Rails/DynamicFindBy
# Ignore local users
@actor = nil if @actor&.local? && @actor.entity.is_a?(User)
# If this is a local actor, go to the real thing
# This will happen if anyone comes here from a remote follow
redirect_to url_for(@actor.entity) if @actor&.local?
rescue ActiveRecord::RecordNotFound
end
# If not local, we show a follow button and some details of the account
@actors = @actor.nil? ?
# If there's no actor still, run a search
search(@query) :
[@actor]
else
# Get recommended follows from FASPs if there's no query
get_recommended_accounts
end
end
# Outgoing remote follow - ask for target account
def remote_follow
@remote_account = cookies[:fediverse_account]
@name = params[:name]
@uri = params[:uri]
end
# Outgoing remote follow - perform webfinger, then redirect
def perform_remote_follow
@remote_account = params[:remote_account]
parts = Fediverse::Webfinger.split_account(@remote_account)
target = Fediverse::Webfinger.remote_follow_url(parts[:username], parts[:domain], actor_url: params[:uri])
# Store remote username in a cookie for future convenience
cookies[:fediverse_account] = @remote_account
# And off we go
redirect_to target, allow_other_host: true
rescue ActiveRecord::RecordNotFound, NoMethodError
@name = params[:name]
@uri = params[:uri]
render :remote_follow
end
def follow_remote_actor
authorize Federails::Following, :create?
@actor = Federails::Actor.find_param(params[:id])
current_user.follow(@actor)
redirect_back_or_to root_url, notice: t(".followed", actor: @actor.at_address)
end
def unfollow_remote_actor
authorize Federails::Following, :destroy?
@actor = Federails::Actor.find_param(params[:id])
current_user.unfollow(@actor)
redirect_back_or_to root_url, notice: t(".unfollowed", actor: @actor.at_address)
end
def create
authorize Federails::Following
current_user.follow @target
redirect_to @target
end
def destroy
authorize Federails::Following
current_user.unfollow @target
redirect_to @target
end
private
def get_recommended_accounts
@recommended = FaspClient::Provider.find_each.map do |provider|
provider.follow_recommendation(current_user.federails_actor.federated_url)
end.flatten.uniq.map { |it| Federails::Actor.find_or_create_by_federation_url it }.reject(&:local)
end
def search(query)
FaspClient::Provider.find_each.map do |provider|
provider.account_search(query)
end.flatten.uniq.map { |it| Federails::Actor.find_or_create_by_federation_url it }.reject(&:local)
end
def get_target
followable = params[:followable_class].constantize
followable_param = params[:followable_class].parameterize + "_id"
id = params[followable_param]
@target = policy_scope(followable).find_param(id)
end
end