mastodon/app/models/concerns/account_interactions.rb
Eugen Rochko 6793bec4c6
Store URIs of follows, follow requests and blocks for ActivityPub ()
Same URI passed between follow request and follow, since they are
the same thing in ActivityPub. Local URIs are generated during
creation using UUIDs and are passed to serializers.
2018-05-04 21:14:34 +02:00

186 lines
6.8 KiB
Ruby

# frozen_string_literal: true
module AccountInteractions
extend ActiveSupport::Concern
class_methods do
def following_map(target_account_ids, account_id)
Follow.where(target_account_id: target_account_ids, account_id: account_id).each_with_object({}) do |follow, mapping|
mapping[follow.target_account_id] = {
reblogs: follow.show_reblogs?,
}
end
end
def followed_by_map(target_account_ids, account_id)
follow_mapping(Follow.where(account_id: target_account_ids, target_account_id: account_id), :account_id)
end
def blocking_map(target_account_ids, account_id)
follow_mapping(Block.where(target_account_id: target_account_ids, account_id: account_id), :target_account_id)
end
def blocked_by_map(target_account_ids, account_id)
follow_mapping(Block.where(account_id: target_account_ids, target_account_id: account_id), :account_id)
end
def muting_map(target_account_ids, account_id)
Mute.where(target_account_id: target_account_ids, account_id: account_id).each_with_object({}) do |mute, mapping|
mapping[mute.target_account_id] = {
notifications: mute.hide_notifications?,
}
end
end
def requested_map(target_account_ids, account_id)
FollowRequest.where(target_account_id: target_account_ids, account_id: account_id).each_with_object({}) do |follow_request, mapping|
mapping[follow_request.target_account_id] = {
reblogs: follow_request.show_reblogs?,
}
end
end
def domain_blocking_map(target_account_ids, account_id)
accounts_map = Account.where(id: target_account_ids).select('id, domain').map { |a| [a.id, a.domain] }.to_h
blocked_domains = domain_blocking_map_by_domain(accounts_map.values.compact, account_id)
accounts_map.map { |id, domain| [id, blocked_domains[domain]] }.to_h
end
def domain_blocking_map_by_domain(target_domains, account_id)
follow_mapping(AccountDomainBlock.where(account_id: account_id, domain: target_domains), :domain)
end
private
def follow_mapping(query, field)
query.pluck(field).each_with_object({}) { |id, mapping| mapping[id] = true }
end
end
included do
# Follow relations
has_many :follow_requests, dependent: :destroy
has_many :active_relationships, class_name: 'Follow', foreign_key: 'account_id', dependent: :destroy
has_many :passive_relationships, class_name: 'Follow', foreign_key: 'target_account_id', dependent: :destroy
has_many :following, -> { order('follows.id desc') }, through: :active_relationships, source: :target_account
has_many :followers, -> { order('follows.id desc') }, through: :passive_relationships, source: :account
# Block relationships
has_many :block_relationships, class_name: 'Block', foreign_key: 'account_id', dependent: :destroy
has_many :blocking, -> { order('blocks.id desc') }, through: :block_relationships, source: :target_account
has_many :blocked_by_relationships, class_name: 'Block', foreign_key: :target_account_id, dependent: :destroy
has_many :blocked_by, -> { order('blocks.id desc') }, through: :blocked_by_relationships, source: :account
# Mute relationships
has_many :mute_relationships, class_name: 'Mute', foreign_key: 'account_id', dependent: :destroy
has_many :muting, -> { order('mutes.id desc') }, through: :mute_relationships, source: :target_account
has_many :muted_by_relationships, class_name: 'Mute', foreign_key: :target_account_id, dependent: :destroy
has_many :muted_by, -> { order('mutes.id desc') }, through: :muted_by_relationships, source: :account
has_many :conversation_mutes, dependent: :destroy
has_many :domain_blocks, class_name: 'AccountDomainBlock', dependent: :destroy
end
def follow!(other_account, reblogs: nil, uri: nil)
reblogs = true if reblogs.nil?
rel = active_relationships.create_with(show_reblogs: reblogs, uri: uri)
.find_or_create_by!(target_account: other_account)
rel.update!(show_reblogs: reblogs)
rel
end
def block!(other_account, uri: nil)
block_relationships.create_with(uri: uri)
.find_or_create_by!(target_account: other_account)
end
def mute!(other_account, notifications: nil)
notifications = true if notifications.nil?
mute = mute_relationships.create_with(hide_notifications: notifications).find_or_create_by!(target_account: other_account)
# When toggling a mute between hiding and allowing notifications, the mute will already exist, so the find_or_create_by! call will return the existing Mute without updating the hide_notifications attribute. Therefore, we check that hide_notifications? is what we want and set it if it isn't.
if mute.hide_notifications? != notifications
mute.update!(hide_notifications: notifications)
end
mute
end
def mute_conversation!(conversation)
conversation_mutes.find_or_create_by!(conversation: conversation)
end
def block_domain!(other_domain)
domain_blocks.find_or_create_by!(domain: other_domain)
end
def unfollow!(other_account)
follow = active_relationships.find_by(target_account: other_account)
follow&.destroy
end
def unblock!(other_account)
block = block_relationships.find_by(target_account: other_account)
block&.destroy
end
def unmute!(other_account)
mute = mute_relationships.find_by(target_account: other_account)
mute&.destroy
end
def unmute_conversation!(conversation)
mute = conversation_mutes.find_by(conversation: conversation)
mute&.destroy!
end
def unblock_domain!(other_domain)
block = domain_blocks.find_by(domain: other_domain)
block&.destroy
end
def following?(other_account)
active_relationships.where(target_account: other_account).exists?
end
def blocking?(other_account)
block_relationships.where(target_account: other_account).exists?
end
def domain_blocking?(other_domain)
domain_blocks.where(domain: other_domain).exists?
end
def muting?(other_account)
mute_relationships.where(target_account: other_account).exists?
end
def muting_conversation?(conversation)
conversation_mutes.where(conversation: conversation).exists?
end
def muting_notifications?(other_account)
mute_relationships.where(target_account: other_account, hide_notifications: true).exists?
end
def muting_reblogs?(other_account)
active_relationships.where(target_account: other_account, show_reblogs: false).exists?
end
def requested?(other_account)
follow_requests.where(target_account: other_account).exists?
end
def favourited?(status)
status.proper.favourites.where(account: self).exists?
end
def reblogged?(status)
status.proper.reblogs.where(account: self).exists?
end
def pinned?(status)
status_pins.where(status: status).exists?
end
end