Improved timeline merge for account subscriptions and add option to subscribe to media only
This commit is contained in:
parent
9720a83867
commit
0d0d754b27
45 changed files with 264 additions and 93 deletions
1
Gemfile
1
Gemfile
|
@ -24,6 +24,7 @@ gem 'paperclip', '~> 6.0'
|
||||||
gem 'blurhash', '~> 0.1'
|
gem 'blurhash', '~> 0.1'
|
||||||
|
|
||||||
gem 'active_model_serializers', '~> 0.10'
|
gem 'active_model_serializers', '~> 0.10'
|
||||||
|
gem 'active_record_extended', git: 'https://github.com/GeorgeKaraszi/ActiveRecordExtended.git', ref: '8c9d1a3e72aabf1a4f1fbeeb93a6e0f170fd0c3e'
|
||||||
gem 'addressable', '~> 2.8'
|
gem 'addressable', '~> 2.8'
|
||||||
gem 'bootsnap', '~> 1.6.0', require: false
|
gem 'bootsnap', '~> 1.6.0', require: false
|
||||||
gem 'browser'
|
gem 'browser'
|
||||||
|
|
13
Gemfile.lock
13
Gemfile.lock
|
@ -1,3 +1,13 @@
|
||||||
|
GIT
|
||||||
|
remote: https://github.com/GeorgeKaraszi/ActiveRecordExtended.git
|
||||||
|
revision: 8c9d1a3e72aabf1a4f1fbeeb93a6e0f170fd0c3e
|
||||||
|
ref: 8c9d1a3e72aabf1a4f1fbeeb93a6e0f170fd0c3e
|
||||||
|
specs:
|
||||||
|
active_record_extended (2.0.0)
|
||||||
|
activerecord (>= 5.1, < 6.2)
|
||||||
|
ar_outer_joins (~> 0.2)
|
||||||
|
pg (< 3.0)
|
||||||
|
|
||||||
GEM
|
GEM
|
||||||
remote: https://rubygems.org/
|
remote: https://rubygems.org/
|
||||||
specs:
|
specs:
|
||||||
|
@ -74,6 +84,8 @@ GEM
|
||||||
annotate (3.1.1)
|
annotate (3.1.1)
|
||||||
activerecord (>= 3.2, < 7.0)
|
activerecord (>= 3.2, < 7.0)
|
||||||
rake (>= 10.4, < 14.0)
|
rake (>= 10.4, < 14.0)
|
||||||
|
ar_outer_joins (0.2.0)
|
||||||
|
activerecord (>= 3.2)
|
||||||
ast (2.4.2)
|
ast (2.4.2)
|
||||||
attr_encrypted (3.1.0)
|
attr_encrypted (3.1.0)
|
||||||
encryptor (~> 3.0.0)
|
encryptor (~> 3.0.0)
|
||||||
|
@ -668,6 +680,7 @@ PLATFORMS
|
||||||
|
|
||||||
DEPENDENCIES
|
DEPENDENCIES
|
||||||
active_model_serializers (~> 0.10)
|
active_model_serializers (~> 0.10)
|
||||||
|
active_record_extended!
|
||||||
active_record_query_trace (~> 1.8)
|
active_record_query_trace (~> 1.8)
|
||||||
addressable (~> 2.8)
|
addressable (~> 2.8)
|
||||||
annotate (~> 3.1)
|
annotate (~> 3.1)
|
||||||
|
|
|
@ -39,7 +39,7 @@ class Api::V1::AccountsController < Api::BaseController
|
||||||
end
|
end
|
||||||
|
|
||||||
def subscribe
|
def subscribe
|
||||||
AccountSubscribeService.new.call(current_user.account, @account, reblogs: truthy_param?(:reblogs), list_id: params[:list_id])
|
AccountSubscribeService.new.call(current_user.account, @account, reblogs: truthy_param?(:reblogs), media_only: truthy_param?(:media_only) || false, list_id: params[:list_id])
|
||||||
render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships
|
render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -59,7 +59,7 @@ class Api::V1::AccountsController < Api::BaseController
|
||||||
end
|
end
|
||||||
|
|
||||||
def unsubscribe
|
def unsubscribe
|
||||||
UnsubscribeAccountService.new.call(current_user.account, @account, params[:list_id])
|
UnsubscribeAccountService.new.call(current_user.account, @account, list_id: params[:list_id])
|
||||||
render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships
|
render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,6 @@ class Api::V1::DomainSubscribesController < Api::BaseController
|
||||||
end
|
end
|
||||||
|
|
||||||
def domain_subscribe_params
|
def domain_subscribe_params
|
||||||
params.permit(:domain, :list_id, :exclude_reblog)
|
params.permit(:domain, :list_id, :exclude_reblog, :media_only)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -38,6 +38,6 @@ class Api::V1::FollowTagsController < Api::BaseController
|
||||||
end
|
end
|
||||||
|
|
||||||
def follow_tag_params
|
def follow_tag_params
|
||||||
params.permit(:name)
|
params.permit(:name, :media_only)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -44,6 +44,6 @@ class Api::V1::KeywordSubscribesController < Api::BaseController
|
||||||
end
|
end
|
||||||
|
|
||||||
def resource_params
|
def resource_params
|
||||||
params.permit(:name, :keyword, :exclude_keyword, :ignorecase, :regexp, :ignore_block, :disabled, :list_id)
|
params.permit(:name, :keyword, :exclude_keyword, :ignorecase, :regexp, :ignore_block, :media_only, :disabled, :list_id)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -16,7 +16,7 @@ class Settings::AccountSubscribesController < Settings::BaseController
|
||||||
|
|
||||||
def create
|
def create
|
||||||
@form_account_subscribing = Form::AccountSubscribe.new(account_subscribe_params)
|
@form_account_subscribing = Form::AccountSubscribe.new(account_subscribe_params)
|
||||||
target_account = AccountSubscribeService.new.call(current_account, @form_account_subscribing.acct, { show_reblogs: @form_account_subscribing.show_reblogs, list_id: @form_account_subscribing.list_id })
|
target_account = AccountSubscribeService.new.call(current_account, @form_account_subscribing.acct, { show_reblogs: @form_account_subscribing.show_reblogs, list_id: @form_account_subscribing.list_id, media_only: @form_account_subscribing.media_only })
|
||||||
|
|
||||||
if target_account
|
if target_account
|
||||||
redirect_to settings_account_subscribes_path
|
redirect_to settings_account_subscribes_path
|
||||||
|
@ -38,7 +38,7 @@ class Settings::AccountSubscribesController < Settings::BaseController
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
UnsubscribeAccountService.new.call(current_account, @account_subscribing.target_account, @account_subscribing.list_id)
|
UnsubscribeAccountService.new.call(current_account, @account_subscribing.target_account, list_id: @account_subscribing.list_id)
|
||||||
redirect_to settings_account_subscribes_path
|
redirect_to settings_account_subscribes_path
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@ class Settings::AccountSubscribesController < Settings::BaseController
|
||||||
|
|
||||||
def set_account_subscribing
|
def set_account_subscribing
|
||||||
@account_subscribing = current_account.active_subscribes.find(params[:id])
|
@account_subscribing = current_account.active_subscribes.find(params[:id])
|
||||||
@form_account_subscribing = Form::AccountSubscribe.new(id: @account_subscribing.id, acct: @account_subscribing.target_account.acct, show_reblogs: @account_subscribing.show_reblogs, list_id: @account_subscribing.list_id)
|
@form_account_subscribing = Form::AccountSubscribe.new(id: @account_subscribing.id, acct: @account_subscribing.target_account.acct, show_reblogs: @account_subscribing.show_reblogs, list_id: @account_subscribing.list_id, media_only: @account_subscribing.media_only)
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_account_subscribings
|
def set_account_subscribings
|
||||||
|
@ -69,6 +69,6 @@ class Settings::AccountSubscribesController < Settings::BaseController
|
||||||
end
|
end
|
||||||
|
|
||||||
def resource_params
|
def resource_params
|
||||||
params.require(:form_account_subscribe).permit(:acct, :show_reblogs, :list_id)
|
params.require(:form_account_subscribe).permit(:acct, :show_reblogs, :list_id, :media_only)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -68,6 +68,6 @@ class Settings::DomainSubscribesController < Settings::BaseController
|
||||||
end
|
end
|
||||||
|
|
||||||
def resource_params
|
def resource_params
|
||||||
params.require(:domain_subscribe).permit(:domain, :list_id, :exclude_reblog)
|
params.require(:domain_subscribe).permit(:domain, :list_id, :exclude_reblog, :media_only)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -69,6 +69,6 @@ class Settings::FollowTagsController < Settings::BaseController
|
||||||
end
|
end
|
||||||
|
|
||||||
def resource_params
|
def resource_params
|
||||||
params.require(:follow_tag).permit(:name, :list_id)
|
params.require(:follow_tag).permit(:name, :list_id, :media_only)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -69,7 +69,7 @@ class Settings::KeywordSubscribesController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def resource_params
|
def resource_params
|
||||||
params.require(:keyword_subscribe).permit(:name, :keyword, :exclude_keyword, :ignorecase, :regexp, :ignore_block, :disabled, :list_id)
|
params.require(:keyword_subscribe).permit(:name, :keyword, :exclude_keyword, :ignorecase, :regexp, :ignore_block, :disabled, :list_id, :media_only)
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_body_classes
|
def set_body_classes
|
||||||
|
|
|
@ -14,7 +14,7 @@ class ActivityPub::Activity::Block < ActivityPub::Activity
|
||||||
UnfollowService.new.call(@account, target_account) if @account.following?(target_account)
|
UnfollowService.new.call(@account, target_account) if @account.following?(target_account)
|
||||||
UnfollowService.new.call(target_account, @account) if target_account.following?(@account)
|
UnfollowService.new.call(target_account, @account) if target_account.following?(@account)
|
||||||
RejectFollowService.new.call(target_account, @account) if target_account.requested?(@account)
|
RejectFollowService.new.call(target_account, @account) if target_account.requested?(@account)
|
||||||
UnsubscribeAccountService.new.call(target_account, @account, :all)
|
UnsubscribeAccountService.new.call(target_account, @account, list_id: :all)
|
||||||
|
|
||||||
unless delete_arrived_first?(@json['id'])
|
unless delete_arrived_first?(@json['id'])
|
||||||
BlockWorker.perform_async(@account.id, target_account.id)
|
BlockWorker.perform_async(@account.id, target_account.id)
|
||||||
|
|
|
@ -100,14 +100,41 @@ class FeedManager
|
||||||
# @param [Account] from_account
|
# @param [Account] from_account
|
||||||
# @param [Account] into_account
|
# @param [Account] into_account
|
||||||
# @return [void]
|
# @return [void]
|
||||||
def merge_into_home(from_account, into_account, public_only = false)
|
def merge_into_home(from_account, into_account, options = {})
|
||||||
timeline_key = key(:home, into_account.id)
|
options = { show_reblogs: true }.merge(options)
|
||||||
|
|
||||||
|
if options[:list_id].nil?
|
||||||
|
list = nil
|
||||||
|
type = :home
|
||||||
|
id = into_account.id
|
||||||
|
else
|
||||||
|
list = List.find(options[:list_id])
|
||||||
|
type = :list
|
||||||
|
id = options[:list_id]
|
||||||
|
end
|
||||||
|
|
||||||
|
timeline_key = key(type, id)
|
||||||
aggregate = into_account.user&.aggregates_reblogs?
|
aggregate = into_account.user&.aggregates_reblogs?
|
||||||
query = from_account.statuses.where(visibility: public_only ? :public : [:public, :unlisted, :private]).includes(:preloadable_poll, reblog: :account).limit(FeedManager::MAX_ITEMS / 4)
|
|
||||||
|
query = from_account.statuses
|
||||||
|
query = query.where(visibility: options[:public_only] ? :public : [:public, :unlisted, :private])
|
||||||
|
|
||||||
|
if options[:show_reblogs] && options[:media_only]
|
||||||
|
query = begin
|
||||||
|
Status
|
||||||
|
.union(query.where(reblog_of_id: nil).joins(:media_attachments))
|
||||||
|
.union(query.where.not(reblog_of_id: nil).joins({:reblog => :media_attachments}))
|
||||||
|
end
|
||||||
|
else
|
||||||
|
query = query.joins(:media_attachments) if options[:media_only]
|
||||||
|
query = query.where(reblog_of_id: nil) if options[:show_reblogs] == false
|
||||||
|
end
|
||||||
|
|
||||||
|
query = query.includes(:preloadable_poll, reblog: :account).limit(FeedManager::MAX_ITEMS / 4)
|
||||||
|
|
||||||
if redis.zcard(timeline_key) >= FeedManager::MAX_ITEMS / 4
|
if redis.zcard(timeline_key) >= FeedManager::MAX_ITEMS / 4
|
||||||
oldest_home_score = redis.zrange(timeline_key, 0, 0, with_scores: true).first.last.to_i
|
oldest_home_score = redis.zrange(timeline_key, 0, 0).first.to_i
|
||||||
query = query.where('id > ?', oldest_home_score)
|
query = query.where('id >= ?', oldest_home_score)
|
||||||
end
|
end
|
||||||
|
|
||||||
statuses = query.to_a
|
statuses = query.to_a
|
||||||
|
@ -115,37 +142,20 @@ class FeedManager
|
||||||
|
|
||||||
statuses.each do |status|
|
statuses.each do |status|
|
||||||
next if filter_from_home?(status, into_account.id, crutches)
|
next if filter_from_home?(status, into_account.id, crutches)
|
||||||
|
next if !list.nil? && filter_from_list?(status, list)
|
||||||
|
|
||||||
add_to_feed(:home, into_account.id, status, aggregate)
|
add_to_feed(type, id, status, aggregate)
|
||||||
end
|
end
|
||||||
|
|
||||||
trim(:home, into_account.id)
|
trim(type, id)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Fill a list feed with an account's statuses
|
# Fill a list feed with an account's statuses
|
||||||
# @param [Account] from_account
|
# @param [Account] from_account
|
||||||
# @param [List] list
|
# @param [List] list
|
||||||
# @return [void]
|
# @return [void]
|
||||||
def merge_into_list(from_account, list)
|
def merge_into_list(from_account, list, options = {})
|
||||||
timeline_key = key(:list, list.id)
|
merge_into_home(from_account, list.account, options.merge(list_id: list.id))
|
||||||
aggregate = list.account.user&.aggregates_reblogs?
|
|
||||||
query = from_account.statuses.where(visibility: [:public, :unlisted, :private]).includes(:preloadable_poll, reblog: :account).limit(FeedManager::MAX_ITEMS / 4)
|
|
||||||
|
|
||||||
if redis.zcard(timeline_key) >= FeedManager::MAX_ITEMS / 4
|
|
||||||
oldest_home_score = redis.zrange(timeline_key, 0, 0, with_scores: true).first.last.to_i
|
|
||||||
query = query.where('id > ?', oldest_home_score)
|
|
||||||
end
|
|
||||||
|
|
||||||
statuses = query.to_a
|
|
||||||
crutches = build_crutches(list.account_id, statuses)
|
|
||||||
|
|
||||||
statuses.each do |status|
|
|
||||||
next if filter_from_home?(status, list.account_id, crutches) || filter_from_list?(status, list)
|
|
||||||
|
|
||||||
add_to_feed(:list, list.id, status, aggregate)
|
|
||||||
end
|
|
||||||
|
|
||||||
trim(:list, list.id)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Remove an account's statuses from a home feed
|
# Remove an account's statuses from a home feed
|
||||||
|
@ -154,9 +164,9 @@ class FeedManager
|
||||||
# @return [void]
|
# @return [void]
|
||||||
def unmerge_from_home(from_account, into_account)
|
def unmerge_from_home(from_account, into_account)
|
||||||
timeline_key = key(:home, into_account.id)
|
timeline_key = key(:home, into_account.id)
|
||||||
oldest_home_score = redis.zrange(timeline_key, 0, 0, with_scores: true)&.first&.last&.to_i || 0
|
oldest_home_score = redis.zrange(timeline_key, 0, 0)&.first&.to_i || 0
|
||||||
|
|
||||||
from_account.statuses.select('id, reblog_of_id').where('id > ?', oldest_home_score).reorder(nil).find_each do |status|
|
from_account.statuses.select('id, reblog_of_id').where('id >= ?', oldest_home_score).reorder(nil).find_each do |status|
|
||||||
remove_from_feed(:home, into_account.id, status, into_account.user&.aggregates_reblogs?)
|
remove_from_feed(:home, into_account.id, status, into_account.user&.aggregates_reblogs?)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -167,9 +177,9 @@ class FeedManager
|
||||||
# @return [void]
|
# @return [void]
|
||||||
def unmerge_from_list(from_account, list)
|
def unmerge_from_list(from_account, list)
|
||||||
timeline_key = key(:list, list.id)
|
timeline_key = key(:list, list.id)
|
||||||
oldest_list_score = redis.zrange(timeline_key, 0, 0, with_scores: true)&.first&.last&.to_i || 0
|
oldest_list_score = redis.zrange(timeline_key, 0, 0)&.first&.to_i || 0
|
||||||
|
|
||||||
from_account.statuses.select('id, reblog_of_id').where('id > ?', oldest_list_score).reorder(nil).find_each do |status|
|
from_account.statuses.select('id, reblog_of_id').where('id >= ?', oldest_list_score).reorder(nil).find_each do |status|
|
||||||
remove_from_feed(:list, list.id, status, list.account.user&.aggregates_reblogs?)
|
remove_from_feed(:list, list.id, status, list.account.user&.aggregates_reblogs?)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,10 +5,11 @@
|
||||||
# id :bigint(8) not null, primary key
|
# id :bigint(8) not null, primary key
|
||||||
# account_id :bigint(8)
|
# account_id :bigint(8)
|
||||||
# target_account_id :bigint(8)
|
# target_account_id :bigint(8)
|
||||||
# show_reblogs :boolean default(TRUE), not null
|
|
||||||
# created_at :datetime not null
|
# created_at :datetime not null
|
||||||
# updated_at :datetime not null
|
# updated_at :datetime not null
|
||||||
# list_id :bigint(8)
|
# list_id :bigint(8)
|
||||||
|
# show_reblogs :boolean default(TRUE), not null
|
||||||
|
# media_only :boolean default(FALSE), not null
|
||||||
#
|
#
|
||||||
|
|
||||||
class AccountSubscribe < ApplicationRecord
|
class AccountSubscribe < ApplicationRecord
|
||||||
|
@ -26,6 +27,7 @@ class AccountSubscribe < ApplicationRecord
|
||||||
scope :home, -> { where(list_id: nil) }
|
scope :home, -> { where(list_id: nil) }
|
||||||
scope :list, -> { where.not(list_id: nil) }
|
scope :list, -> { where.not(list_id: nil) }
|
||||||
scope :with_reblog, ->(reblog) { where(show_reblogs: true) if reblog }
|
scope :with_reblog, ->(reblog) { where(show_reblogs: true) if reblog }
|
||||||
|
scope :with_media, ->(status) { where(media_only: false) unless status.with_media? }
|
||||||
|
|
||||||
after_create :increment_cache_counters
|
after_create :increment_cache_counters
|
||||||
after_destroy :decrement_cache_counters
|
after_destroy :decrement_cache_counters
|
||||||
|
|
|
@ -211,11 +211,13 @@ module AccountInteractions
|
||||||
block&.destroy
|
block&.destroy
|
||||||
end
|
end
|
||||||
|
|
||||||
def subscribe!(other_account, reblogs = true, list_id = nil)
|
def subscribe!(other_account, options = {})
|
||||||
rel = active_subscribes.create_with(show_reblogs: reblogs)
|
options = { show_reblogs: true, list_id: nil, media_only: false }.merge(options)
|
||||||
.find_or_create_by!(target_account: other_account, list_id: list_id)
|
|
||||||
|
|
||||||
rel.update!(show_reblogs: reblogs)
|
rel = active_subscribes.create_with(show_reblogs: options[:show_reblogs], media_only: options[:media_only] || false)
|
||||||
|
.find_or_create_by!(target_account: other_account, list_id: options[:list_id])
|
||||||
|
|
||||||
|
rel.update!(show_reblogs: options[:show_reblogs], media_only: options[:media_only] || false)
|
||||||
remove_potential_friendship(other_account)
|
remove_potential_friendship(other_account)
|
||||||
|
|
||||||
rel
|
rel
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
# created_at :datetime not null
|
# created_at :datetime not null
|
||||||
# updated_at :datetime not null
|
# updated_at :datetime not null
|
||||||
# exclude_reblog :boolean default(TRUE)
|
# exclude_reblog :boolean default(TRUE)
|
||||||
|
# media_only :boolean default(FALSE), not null
|
||||||
#
|
#
|
||||||
|
|
||||||
class DomainSubscribe < ApplicationRecord
|
class DomainSubscribe < ApplicationRecord
|
||||||
|
@ -21,4 +22,5 @@ class DomainSubscribe < ApplicationRecord
|
||||||
scope :domain_to_home, ->(domain) { where(domain: domain).where(list_id: nil) }
|
scope :domain_to_home, ->(domain) { where(domain: domain).where(list_id: nil) }
|
||||||
scope :domain_to_list, ->(domain) { where(domain: domain).where.not(list_id: nil) }
|
scope :domain_to_list, ->(domain) { where(domain: domain).where.not(list_id: nil) }
|
||||||
scope :with_reblog, ->(reblog) { where(exclude_reblog: false) if reblog }
|
scope :with_reblog, ->(reblog) { where(exclude_reblog: false) if reblog }
|
||||||
|
scope :with_media, ->(status) { where(media_only: false) unless status.with_media? }
|
||||||
end
|
end
|
||||||
|
|
|
@ -10,9 +10,8 @@
|
||||||
# target_account_id :bigint(8) not null
|
# target_account_id :bigint(8) not null
|
||||||
# show_reblogs :boolean default(TRUE), not null
|
# show_reblogs :boolean default(TRUE), not null
|
||||||
# uri :string
|
# uri :string
|
||||||
# notify :boolean default(FALSE), not null
|
|
||||||
# private :boolean default(TRUE), not null
|
|
||||||
# delivery :boolean default(TRUE), not null
|
# delivery :boolean default(TRUE), not null
|
||||||
|
# notify :boolean default(FALSE), not null
|
||||||
#
|
#
|
||||||
|
|
||||||
class Follow < ApplicationRecord
|
class Follow < ApplicationRecord
|
||||||
|
|
|
@ -31,7 +31,6 @@ class FollowRequest < ApplicationRecord
|
||||||
|
|
||||||
def authorize!
|
def authorize!
|
||||||
account.follow!(target_account, reblogs: show_reblogs, notify: notify, delivery: delivery, uri: uri, bypass_limit: true)
|
account.follow!(target_account, reblogs: show_reblogs, notify: notify, delivery: delivery, uri: uri, bypass_limit: true)
|
||||||
UnsubscribeAccountService.new.call(account, target_account) if account.subscribing?(target_account)
|
|
||||||
MergeWorker.perform_async(target_account.id, account.id) if account.local? && delivery?
|
MergeWorker.perform_async(target_account.id, account.id) if account.local? && delivery?
|
||||||
destroy!
|
destroy!
|
||||||
end
|
end
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
# created_at :datetime not null
|
# created_at :datetime not null
|
||||||
# updated_at :datetime not null
|
# updated_at :datetime not null
|
||||||
# list_id :bigint(8)
|
# list_id :bigint(8)
|
||||||
|
# media_only :boolean default(FALSE), not null
|
||||||
#
|
#
|
||||||
|
|
||||||
class FollowTag < ApplicationRecord
|
class FollowTag < ApplicationRecord
|
||||||
|
@ -23,6 +24,7 @@ class FollowTag < ApplicationRecord
|
||||||
|
|
||||||
scope :home, -> { where(list_id: nil) }
|
scope :home, -> { where(list_id: nil) }
|
||||||
scope :list, -> { where.not(list_id: nil) }
|
scope :list, -> { where.not(list_id: nil) }
|
||||||
|
scope :with_media, ->(status) { where(media_only: false) unless status.with_media? }
|
||||||
|
|
||||||
def name=(str)
|
def name=(str)
|
||||||
self.tag = Tag.find_or_create_by_names(str.strip)&.first
|
self.tag = Tag.find_or_create_by_names(str.strip)&.first
|
||||||
|
|
|
@ -6,6 +6,7 @@ class Form::AccountSubscribe
|
||||||
attribute :acct, :string
|
attribute :acct, :string
|
||||||
attribute :show_reblogs, :boolean, default: true
|
attribute :show_reblogs, :boolean, default: true
|
||||||
attribute :list_id, :integer
|
attribute :list_id, :integer
|
||||||
|
attribute :media_only, :boolean, default: false
|
||||||
|
|
||||||
def acct=(val)
|
def acct=(val)
|
||||||
super(val.to_s.strip.gsub(/\A@/, ''))
|
super(val.to_s.strip.gsub(/\A@/, ''))
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
# disabled :boolean default(FALSE)
|
# disabled :boolean default(FALSE)
|
||||||
# exclude_keyword :string default(""), not null
|
# exclude_keyword :string default(""), not null
|
||||||
# list_id :bigint(8)
|
# list_id :bigint(8)
|
||||||
|
# media_only :boolean default(FALSE), not null
|
||||||
#
|
#
|
||||||
|
|
||||||
class KeywordSubscribe < ApplicationRecord
|
class KeywordSubscribe < ApplicationRecord
|
||||||
|
@ -30,8 +31,9 @@ class KeywordSubscribe < ApplicationRecord
|
||||||
scope :ignore_block, -> { where(ignore_block: true) }
|
scope :ignore_block, -> { where(ignore_block: true) }
|
||||||
scope :home, -> { where(list_id: nil) }
|
scope :home, -> { where(list_id: nil) }
|
||||||
scope :list, -> { where.not(list_id: nil) }
|
scope :list, -> { where.not(list_id: nil) }
|
||||||
scope :without_local_followed_home, ->(account) { home.where.not(account: account.delivery_followers.local).where.not(account: account.subscribers.local) }
|
scope :without_local_followed_home, ->(account) { home.where.not(account: account.delivery_followers.local) }
|
||||||
scope :without_local_followed_list, ->(account) { list.where.not(list_id: ListAccount.followed_lists(account)).where.not(list_id: AccountSubscribe.subscribed_lists(account)) }
|
scope :without_local_followed_list, ->(account) { list.where.not(list_id: ListAccount.followed_lists(account)) }
|
||||||
|
scope :with_media, ->(status) { where(media_only: false) unless status.with_media? }
|
||||||
|
|
||||||
def keyword=(val)
|
def keyword=(val)
|
||||||
super(regexp ? val : keyword_normalization(val))
|
super(regexp ? val : keyword_normalization(val))
|
||||||
|
|
|
@ -5,30 +5,38 @@ class AccountSubscribeService < BaseService
|
||||||
# @param [Account] source_account From which to subscribe
|
# @param [Account] source_account From which to subscribe
|
||||||
# @param [String, Account] uri User URI to subscribe in the form of username@domain (or account record)
|
# @param [String, Account] uri User URI to subscribe in the form of username@domain (or account record)
|
||||||
def call(source_account, target_acct, options = {})
|
def call(source_account, target_acct, options = {})
|
||||||
@options = { show_reblogs: true, list_id: nil }.merge(options)
|
@source_account = source_account
|
||||||
|
@options = { show_reblogs: true, list_id: nil, media_only: false }.merge(options)
|
||||||
|
|
||||||
if target_acct.class.name == 'Account'
|
if target_acct.class.name == 'Account'
|
||||||
target_account = target_acct
|
@target_account = target_acct
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
target_account = ResolveAccountService.new.call(target_acct, skip_webfinger: true)
|
@target_account = ResolveAccountService.new.call(target_acct, skip_webfinger: true)
|
||||||
target_account ||= ResolveAccountService.new.call(target_acct, skip_webfinger: false)
|
@target_account ||= ResolveAccountService.new.call(target_acct, skip_webfinger: false)
|
||||||
rescue
|
rescue
|
||||||
target_account = nil
|
@target_account = nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
raise ActiveRecord::RecordNotFound if target_account.nil? || target_account.id == source_account.id || target_account.suspended?
|
raise ActiveRecord::RecordNotFound if @target_account.nil? || @target_account.id == @source_account.id || @target_account.suspended?
|
||||||
raise Mastodon::NotPermittedError if target_account.blocking?(source_account) || source_account.blocking?(target_account) || (!target_account.local? && target_account.ostatus?) || source_account.domain_blocking?(target_account.domain)
|
raise Mastodon::NotPermittedError if @target_account.blocking?(@source_account) || @source_account.blocking?(@target_account) || (!@target_account.local? && @target_account.ostatus?) || @source_account.domain_blocking?(@target_account.domain)
|
||||||
|
|
||||||
if source_account.subscribing?(target_account, @options[:list_id])
|
if @source_account.subscribing?(@target_account, @options[:list_id])
|
||||||
return
|
return change_subscribe_options!
|
||||||
end
|
end
|
||||||
|
|
||||||
ActivityTracker.increment('activity:interactions')
|
ActivityTracker.increment('activity:interactions')
|
||||||
|
|
||||||
subscribe = source_account.subscribe!(target_account, @options[:show_reblogs], @options[:list_id])
|
subscribe = @source_account.subscribe!(@target_account, @options)
|
||||||
MergeWorker.perform_async(target_account.id, source_account.id, true) if @options[:list_id].nil?
|
MergeWorker.perform_async(@target_account.id, @source_account.id, @options.merge(public_only: true))
|
||||||
subscribe
|
subscribe
|
||||||
end
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def change_subscribe_options!
|
||||||
|
@source_account.subscribe!(@target_account, @options)
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -9,8 +9,8 @@ class BlockService < BaseService
|
||||||
UnfollowService.new.call(account, target_account) if account.following?(target_account)
|
UnfollowService.new.call(account, target_account) if account.following?(target_account)
|
||||||
UnfollowService.new.call(target_account, account) if target_account.following?(account)
|
UnfollowService.new.call(target_account, account) if target_account.following?(account)
|
||||||
RejectFollowService.new.call(target_account, account) if target_account.requested?(account)
|
RejectFollowService.new.call(target_account, account) if target_account.requested?(account)
|
||||||
UnsubscribeAccountService.new.call(account, target_account, :all)
|
UnsubscribeAccountService.new.call(account, target_account, list_id: :all)
|
||||||
UnsubscribeAccountService.new.call(target_account, account, :all)
|
UnsubscribeAccountService.new.call(target_account, account, list_id: :all)
|
||||||
|
|
||||||
block = account.block!(target_account)
|
block = account.block!(target_account)
|
||||||
|
|
||||||
|
|
|
@ -68,7 +68,7 @@ class FanOutOnWriteService < BaseService
|
||||||
def deliver_to_subscribers(status)
|
def deliver_to_subscribers(status)
|
||||||
Rails.logger.debug "Delivering status #{status.id} to subscribers"
|
Rails.logger.debug "Delivering status #{status.id} to subscribers"
|
||||||
|
|
||||||
status.account.subscribers_for_local_distribution.with_reblog(status.reblog?).select(:id, :account_id).reorder(nil).find_in_batches do |subscribings|
|
status.account.subscribers_for_local_distribution.with_reblog(status.reblog?).with_media(status.proper).select(:id, :account_id).reorder(nil).find_in_batches do |subscribings|
|
||||||
FeedInsertWorker.push_bulk(subscribings) do |subscribing|
|
FeedInsertWorker.push_bulk(subscribings) do |subscribing|
|
||||||
[status.id, subscribing.account_id, :home]
|
[status.id, subscribing.account_id, :home]
|
||||||
end
|
end
|
||||||
|
@ -78,7 +78,7 @@ class FanOutOnWriteService < BaseService
|
||||||
def deliver_to_subscribers_lists(status)
|
def deliver_to_subscribers_lists(status)
|
||||||
Rails.logger.debug "Delivering status #{status.id} to subscribers lists"
|
Rails.logger.debug "Delivering status #{status.id} to subscribers lists"
|
||||||
|
|
||||||
status.account.list_subscribers_for_local_distribution.with_reblog(status.reblog?).select(:id, :list_id).reorder(nil).find_in_batches do |subscribings|
|
status.account.list_subscribers_for_local_distribution.with_reblog(status.reblog?).with_media(status.proper).select(:id, :list_id).reorder(nil).find_in_batches do |subscribings|
|
||||||
FeedInsertWorker.push_bulk(subscribings) do |subscribing|
|
FeedInsertWorker.push_bulk(subscribings) do |subscribing|
|
||||||
[status.id, subscribing.list_id, :list]
|
[status.id, subscribing.list_id, :list]
|
||||||
end
|
end
|
||||||
|
@ -93,7 +93,7 @@ class FanOutOnWriteService < BaseService
|
||||||
end
|
end
|
||||||
|
|
||||||
def deliver_to_domain_subscribers_home(status)
|
def deliver_to_domain_subscribers_home(status)
|
||||||
DomainSubscribe.domain_to_home(status.account.domain).with_reblog(status.reblog?).select(:id, :account_id).find_in_batches do |subscribes|
|
DomainSubscribe.domain_to_home(status.account.domain).with_reblog(status.reblog?).with_media(status.proper).select(:id, :account_id).find_in_batches do |subscribes|
|
||||||
FeedInsertWorker.push_bulk(subscribes) do |subscribe|
|
FeedInsertWorker.push_bulk(subscribes) do |subscribe|
|
||||||
[status.id, subscribe.account_id, :home]
|
[status.id, subscribe.account_id, :home]
|
||||||
end
|
end
|
||||||
|
@ -101,7 +101,7 @@ class FanOutOnWriteService < BaseService
|
||||||
end
|
end
|
||||||
|
|
||||||
def deliver_to_domain_subscribers_list(status)
|
def deliver_to_domain_subscribers_list(status)
|
||||||
DomainSubscribe.domain_to_list(status.account.domain).with_reblog(status.reblog?).select(:id, :list_id).find_in_batches do |subscribes|
|
DomainSubscribe.domain_to_list(status.account.domain).with_reblog(status.reblog?).with_media(status.proper).select(:id, :list_id).find_in_batches do |subscribes|
|
||||||
FeedInsertWorker.push_bulk(subscribes) do |subscribe|
|
FeedInsertWorker.push_bulk(subscribes) do |subscribe|
|
||||||
[status.id, subscribe.list_id, :list]
|
[status.id, subscribe.list_id, :list]
|
||||||
end
|
end
|
||||||
|
@ -118,7 +118,7 @@ class FanOutOnWriteService < BaseService
|
||||||
def deliver_to_keyword_subscribers_home(status)
|
def deliver_to_keyword_subscribers_home(status)
|
||||||
match_accounts = []
|
match_accounts = []
|
||||||
|
|
||||||
KeywordSubscribe.active.without_local_followed_home(status.account).order(:account_id).each do |keyword_subscribe|
|
KeywordSubscribe.active.with_media(status.proper).without_local_followed_home(status.account).order(:account_id).each do |keyword_subscribe|
|
||||||
next if match_accounts[-1] == keyword_subscribe.account_id
|
next if match_accounts[-1] == keyword_subscribe.account_id
|
||||||
match_accounts << keyword_subscribe.account_id if keyword_subscribe.match?(status.index_text)
|
match_accounts << keyword_subscribe.account_id if keyword_subscribe.match?(status.index_text)
|
||||||
end
|
end
|
||||||
|
@ -131,7 +131,7 @@ class FanOutOnWriteService < BaseService
|
||||||
def deliver_to_keyword_subscribers_list(status)
|
def deliver_to_keyword_subscribers_list(status)
|
||||||
match_lists = []
|
match_lists = []
|
||||||
|
|
||||||
KeywordSubscribe.active.without_local_followed_list(status.account).order(:list_id).each do |keyword_subscribe|
|
KeywordSubscribe.active.with_media(status.proper).without_local_followed_list(status.account).order(:list_id).each do |keyword_subscribe|
|
||||||
next if match_lists[-1] == keyword_subscribe.list_id
|
next if match_lists[-1] == keyword_subscribe.list_id
|
||||||
match_lists << keyword_subscribe.list_id if keyword_subscribe.match?(status.index_text)
|
match_lists << keyword_subscribe.list_id if keyword_subscribe.match?(status.index_text)
|
||||||
end
|
end
|
||||||
|
@ -191,13 +191,13 @@ class FanOutOnWriteService < BaseService
|
||||||
end
|
end
|
||||||
|
|
||||||
def deliver_to_hashtag_followers_home(status)
|
def deliver_to_hashtag_followers_home(status)
|
||||||
FeedInsertWorker.push_bulk(FollowTag.home.where(tag: status.tags).pluck(:account_id).uniq) do |follower|
|
FeedInsertWorker.push_bulk(FollowTag.home.where(tag: status.tags).with_media(status.proper).pluck(:account_id).uniq) do |follower|
|
||||||
[status.id, follower, :home]
|
[status.id, follower, :home]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def deliver_to_hashtag_followers_list(status)
|
def deliver_to_hashtag_followers_list(status)
|
||||||
FeedInsertWorker.push_bulk(FollowTag.list.where(tag: status.tags).pluck(:list_id).uniq) do |list_id|
|
FeedInsertWorker.push_bulk(FollowTag.list.where(tag: status.tags).with_media(status.proper).pluck(:list_id).uniq) do |list_id|
|
||||||
[status.id, list_id, :list]
|
[status.id, list_id, :list]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -4,20 +4,21 @@ class UnsubscribeAccountService < BaseService
|
||||||
# UnsubscribeAccount
|
# UnsubscribeAccount
|
||||||
# @param [Account] source_account Where to unsubscribe from
|
# @param [Account] source_account Where to unsubscribe from
|
||||||
# @param [Account] target_account Which to unsubscribe
|
# @param [Account] target_account Which to unsubscribe
|
||||||
def call(source_account, target_account, list_id = nil)
|
def call(source_account, target_account, options = {})
|
||||||
if (list_id == :all)
|
if (options[:list_id] == :all)
|
||||||
AccountSubscribe.where(account: source_account, target_account: target_account).each do |subscribe|
|
subscribes = AccountSubscribe.where(account: source_account, target_account: target_account)
|
||||||
|
else
|
||||||
|
subscribes = AccountSubscribe.where(account: source_account, target_account: target_account, list_id: options[:list_id])
|
||||||
|
end
|
||||||
|
|
||||||
|
subscribes.each do |subscribe|
|
||||||
|
list_id = subscribe.list_id
|
||||||
subscribe.destroy!
|
subscribe.destroy!
|
||||||
UnmergeWorker.perform_async(target_account.id, source_account.id) if subscribe.list_id.nil?
|
if list_id.nil? && !source_account.delivery_following?(target_account)
|
||||||
|
UnmergeWorker.perform_async(target_account.id, source_account.id)
|
||||||
|
elsif !ListAccount.where(list_id: list_id, account_id: target_account.id).exists?
|
||||||
|
UnmergeWorker.perform_async(target_account.id, source_account.id, list_id: list_id)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
subscribe = AccountSubscribe.find_by(account: source_account, target_account: target_account, list_id: list_id)
|
|
||||||
|
|
||||||
return unless subscribe
|
|
||||||
|
|
||||||
subscribe.destroy!
|
|
||||||
UnmergeWorker.perform_async(target_account.id, source_account.id) if list_id.nil?
|
|
||||||
subscribe
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -4,6 +4,9 @@
|
||||||
%td.nowrap.symbol
|
%td.nowrap.symbol
|
||||||
- if account_subscribe.show_reblogs
|
- if account_subscribe.show_reblogs
|
||||||
= fa_icon('check')
|
= fa_icon('check')
|
||||||
|
%td.nowrap.symbol
|
||||||
|
- if account_subscribe.media_only
|
||||||
|
= fa_icon('check')
|
||||||
%td.nowrap
|
%td.nowrap
|
||||||
- if account_subscribe.list_id
|
- if account_subscribe.list_id
|
||||||
= fa_icon 'list-ul'
|
= fa_icon 'list-ul'
|
||||||
|
|
|
@ -4,6 +4,9 @@
|
||||||
.fields-group
|
.fields-group
|
||||||
= f.input :show_reblogs, as: :boolean, wrapper: :with_label
|
= f.input :show_reblogs, as: :boolean, wrapper: :with_label
|
||||||
|
|
||||||
|
.fields-group
|
||||||
|
= f.input :media_only, as: :boolean, wrapper: :with_label
|
||||||
|
|
||||||
.fields-group
|
.fields-group
|
||||||
= f.label :list_id
|
= f.label :list_id
|
||||||
= f.collection_select :list_id, home_list_new(@lists), :first, :last
|
= f.collection_select :list_id, home_list_new(@lists), :first, :last
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
%tr
|
%tr
|
||||||
%th= t('simple_form.labels.form_account_subscribe.acct')
|
%th= t('simple_form.labels.form_account_subscribe.acct')
|
||||||
%th.nowrap.symbol= t('simple_form.labels.form_account_subscribe.reblog')
|
%th.nowrap.symbol= t('simple_form.labels.form_account_subscribe.reblog')
|
||||||
|
%th.nowrap.symbol= t('simple_form.labels.form_account_subscribe.media_only')
|
||||||
%th.nowrap= t('simple_form.labels.form_account_subscribe.timeline')
|
%th.nowrap= t('simple_form.labels.form_account_subscribe.timeline')
|
||||||
%th.nowrap
|
%th.nowrap
|
||||||
%tbody
|
%tbody
|
||||||
|
|
|
@ -4,6 +4,9 @@
|
||||||
%td.nowrap.symbol
|
%td.nowrap.symbol
|
||||||
- if domain_subscribe.exclude_reblog
|
- if domain_subscribe.exclude_reblog
|
||||||
= fa_icon('times')
|
= fa_icon('times')
|
||||||
|
%td.nowrap.symbol
|
||||||
|
- if domain_subscribe.media_only
|
||||||
|
= fa_icon('check')
|
||||||
%td.nowrap
|
%td.nowrap
|
||||||
- if domain_subscribe.list_id
|
- if domain_subscribe.list_id
|
||||||
= fa_icon 'list-ul'
|
= fa_icon 'list-ul'
|
||||||
|
|
|
@ -4,6 +4,9 @@
|
||||||
.fields-group
|
.fields-group
|
||||||
= f.input :exclude_reblog, wrapper: :with_label
|
= f.input :exclude_reblog, wrapper: :with_label
|
||||||
|
|
||||||
|
.fields-group
|
||||||
|
= f.input :media_only, as: :boolean, wrapper: :with_label
|
||||||
|
|
||||||
.fields-group
|
.fields-group
|
||||||
= f.label :list_id
|
= f.label :list_id
|
||||||
= f.collection_select :list_id, home_list_new(@lists), :first, :last
|
= f.collection_select :list_id, home_list_new(@lists), :first, :last
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
%tr
|
%tr
|
||||||
%th= t('simple_form.labels.domain_subscribe.domain')
|
%th= t('simple_form.labels.domain_subscribe.domain')
|
||||||
%th.nowrap.symbol= t('simple_form.labels.domain_subscribe.reblog')
|
%th.nowrap.symbol= t('simple_form.labels.domain_subscribe.reblog')
|
||||||
|
%th.nowrap.symbol= t('simple_form.labels.domain_subscribe.media_only')
|
||||||
%th.nowrap= t('simple_form.labels.domain_subscribe.timeline')
|
%th.nowrap= t('simple_form.labels.domain_subscribe.timeline')
|
||||||
%th.nowrap
|
%th.nowrap
|
||||||
%tbody
|
%tbody
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
.fields-group
|
.fields-group
|
||||||
= f.input :name, wrapper: :with_label
|
= f.input :name, wrapper: :with_label
|
||||||
|
|
||||||
|
.fields-group
|
||||||
|
= f.input :media_only, as: :boolean, wrapper: :with_label
|
||||||
|
|
||||||
.fields-group
|
.fields-group
|
||||||
= f.label :list_id
|
= f.label :list_id
|
||||||
= f.collection_select :list_id, home_list_new(@lists), :first, :last
|
= f.collection_select :list_id, home_list_new(@lists), :first, :last
|
||||||
|
|
|
@ -2,6 +2,9 @@
|
||||||
%td
|
%td
|
||||||
= fa_icon 'hashtag'
|
= fa_icon 'hashtag'
|
||||||
= follow_tag.name
|
= follow_tag.name
|
||||||
|
%td.nowrap.symbol
|
||||||
|
- if follow_tag.media_only
|
||||||
|
= fa_icon('check')
|
||||||
%td.nowrap
|
%td.nowrap
|
||||||
- if follow_tag.list_id
|
- if follow_tag.list_id
|
||||||
= fa_icon 'list-ul'
|
= fa_icon 'list-ul'
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
%thead
|
%thead
|
||||||
%tr
|
%tr
|
||||||
%th= t('simple_form.labels.follow_tag.name')
|
%th= t('simple_form.labels.follow_tag.name')
|
||||||
|
%th.nowrap.symbol= t('simple_form.labels.follow_tag.media_only')
|
||||||
%th.nowrap= t('simple_form.labels.follow_tag.timeline')
|
%th.nowrap= t('simple_form.labels.follow_tag.timeline')
|
||||||
%th.nowrap
|
%th.nowrap
|
||||||
%tbody
|
%tbody
|
||||||
|
|
|
@ -16,6 +16,9 @@
|
||||||
.fields-group
|
.fields-group
|
||||||
= f.input :ignore_block, wrapper: :with_label
|
= f.input :ignore_block, wrapper: :with_label
|
||||||
|
|
||||||
|
.fields-group
|
||||||
|
= f.input :media_only, as: :boolean, wrapper: :with_label
|
||||||
|
|
||||||
.fields-group
|
.fields-group
|
||||||
= f.label :list_id
|
= f.label :list_id
|
||||||
= f.collection_select :list_id, home_list_new(@lists), :first, :last
|
= f.collection_select :list_id, home_list_new(@lists), :first, :last
|
||||||
|
|
|
@ -18,6 +18,9 @@
|
||||||
%td.nowrap
|
%td.nowrap
|
||||||
- if keyword_subscribe.ignore_block
|
- if keyword_subscribe.ignore_block
|
||||||
= t 'keyword_subscribes.ignore_block'
|
= t 'keyword_subscribes.ignore_block'
|
||||||
|
%td.nowrap.symbol
|
||||||
|
- if keyword_subscribe.media_only
|
||||||
|
= fa_icon('check')
|
||||||
%td.nowrap
|
%td.nowrap
|
||||||
- if keyword_subscribe.list_id
|
- if keyword_subscribe.list_id
|
||||||
= fa_icon 'list-ul'
|
= fa_icon 'list-ul'
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
%th= t('simple_form.labels.keyword_subscribes.keyword')
|
%th= t('simple_form.labels.keyword_subscribes.keyword')
|
||||||
%th.nowrap= t('simple_form.labels.keyword_subscribes.ignorecase')
|
%th.nowrap= t('simple_form.labels.keyword_subscribes.ignorecase')
|
||||||
%th.nowrap= t('simple_form.labels.keyword_subscribes.ignore_block')
|
%th.nowrap= t('simple_form.labels.keyword_subscribes.ignore_block')
|
||||||
|
%th.nowrap= t('simple_form.labels.keyword_subscribes.media_only')
|
||||||
%th.nowrap= t('simple_form.labels.keyword_subscribes.timeline')
|
%th.nowrap= t('simple_form.labels.keyword_subscribes.timeline')
|
||||||
%th.nowrap= t('simple_form.labels.keyword_subscribes.disabled')
|
%th.nowrap= t('simple_form.labels.keyword_subscribes.disabled')
|
||||||
%th.nowrap
|
%th.nowrap
|
||||||
|
|
|
@ -3,8 +3,14 @@
|
||||||
class MergeWorker
|
class MergeWorker
|
||||||
include Sidekiq::Worker
|
include Sidekiq::Worker
|
||||||
|
|
||||||
def perform(from_account_id, into_account_id, public_only = false)
|
def perform(from_account_id, into_account_id, options = {})
|
||||||
FeedManager.instance.merge_into_home(Account.find(from_account_id), Account.find(into_account_id), public_only)
|
options.symbolize_keys!
|
||||||
|
|
||||||
|
if options[:list_id].nil?
|
||||||
|
FeedManager.instance.merge_into_home(Account.find(from_account_id), Account.find(into_account_id), options)
|
||||||
|
else
|
||||||
|
FeedManager.instance.merge_into_list(Account.find(from_account_id), List.find(options[:list_id]), options)
|
||||||
|
end
|
||||||
rescue ActiveRecord::RecordNotFound
|
rescue ActiveRecord::RecordNotFound
|
||||||
true
|
true
|
||||||
ensure
|
ensure
|
||||||
|
|
|
@ -5,8 +5,14 @@ class UnmergeWorker
|
||||||
|
|
||||||
sidekiq_options queue: 'pull'
|
sidekiq_options queue: 'pull'
|
||||||
|
|
||||||
def perform(from_account_id, into_account_id)
|
def perform(from_account_id, into_account_id, options = {})
|
||||||
|
options.symbolize_keys!
|
||||||
|
|
||||||
|
if options[:list_id].nil?
|
||||||
FeedManager.instance.unmerge_from_home(Account.find(from_account_id), Account.find(into_account_id))
|
FeedManager.instance.unmerge_from_home(Account.find(from_account_id), Account.find(into_account_id))
|
||||||
|
else
|
||||||
|
FeedManager.instance.unmerge_from_list(Account.find(from_account_id), List.find(options[:list_id]))
|
||||||
|
end
|
||||||
rescue ActiveRecord::RecordNotFound
|
rescue ActiveRecord::RecordNotFound
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
|
|
@ -71,15 +71,18 @@ en:
|
||||||
domain_subscribe:
|
domain_subscribe:
|
||||||
domain: Specify the domain name of the server you want to subscribe to
|
domain: Specify the domain name of the server you want to subscribe to
|
||||||
exclude_reblog: Exclude boosted posts from subscription
|
exclude_reblog: Exclude boosted posts from subscription
|
||||||
|
media_only: Target only statuses with media attached
|
||||||
email_domain_block:
|
email_domain_block:
|
||||||
domain: This can be the domain name that shows up in the e-mail address, the MX record that domain resolves to, or IP of the server that MX record resolves to. Those will be checked upon user sign-up and the sign-up will be rejected.
|
domain: This can be the domain name that shows up in the e-mail address, the MX record that domain resolves to, or IP of the server that MX record resolves to. Those will be checked upon user sign-up and the sign-up will be rejected.
|
||||||
with_dns_records: An attempt to resolve the given domain's DNS records will be made and the results will also be blocked
|
with_dns_records: An attempt to resolve the given domain's DNS records will be made and the results will also be blocked
|
||||||
featured_tag:
|
featured_tag:
|
||||||
name: 'You might want to use one of these:'
|
name: 'You might want to use one of these:'
|
||||||
follow_tag:
|
follow_tag:
|
||||||
|
media_only: Target only statuses with media attached
|
||||||
name: Specify the name of the hashtag without '#' you want to follow
|
name: Specify the name of the hashtag without '#' you want to follow
|
||||||
form_account_subscribe:
|
form_account_subscribe:
|
||||||
acct: Specify the username@domain of the account you want to subscribe
|
acct: Specify the username@domain of the account you want to subscribe
|
||||||
|
media_only: Target only statuses with media attached
|
||||||
show_reblogs: Show boosted posts from subscription
|
show_reblogs: Show boosted posts from subscription
|
||||||
form_challenge:
|
form_challenge:
|
||||||
current_password: You are entering a secure area
|
current_password: You are entering a secure area
|
||||||
|
@ -99,6 +102,7 @@ en:
|
||||||
exclude_keyword: List multiple excluded keywords separated by commas (or use regular expressions)
|
exclude_keyword: List multiple excluded keywords separated by commas (or use regular expressions)
|
||||||
ignore_block: You can prioritize keyword subscriptions while keeping the entire domain block
|
ignore_block: You can prioritize keyword subscriptions while keeping the entire domain block
|
||||||
keyword: List multiple keywords separated by commas (or use regular expressions)
|
keyword: List multiple keywords separated by commas (or use regular expressions)
|
||||||
|
media_only: Target only statuses with media attached
|
||||||
name: Optional
|
name: Optional
|
||||||
rule:
|
rule:
|
||||||
text: Describe a rule or requirement for users on this server. Try to keep it short and simple
|
text: Describe a rule or requirement for users on this server. Try to keep it short and simple
|
||||||
|
@ -210,6 +214,7 @@ en:
|
||||||
domain: Domain
|
domain: Domain
|
||||||
exclude_reblog: Exclude boost
|
exclude_reblog: Exclude boost
|
||||||
list_id: Target timeline
|
list_id: Target timeline
|
||||||
|
media_only: Media only
|
||||||
timeline: Timeline
|
timeline: Timeline
|
||||||
reblog: Boost
|
reblog: Boost
|
||||||
email_domain_block:
|
email_domain_block:
|
||||||
|
@ -218,11 +223,13 @@ en:
|
||||||
name: Hashtag
|
name: Hashtag
|
||||||
follow_tag:
|
follow_tag:
|
||||||
list_id: Target timeline
|
list_id: Target timeline
|
||||||
|
media_only: Media only
|
||||||
name: Tag name
|
name: Tag name
|
||||||
timeline: Timeline
|
timeline: Timeline
|
||||||
form_account_subscribe:
|
form_account_subscribe:
|
||||||
acct: Account
|
acct: Account
|
||||||
list_id: Target timeline
|
list_id: Target timeline
|
||||||
|
media_only: Media only
|
||||||
reblog: Boost
|
reblog: Boost
|
||||||
show_reblogs: Show boost
|
show_reblogs: Show boost
|
||||||
timeline: Timeline
|
timeline: Timeline
|
||||||
|
@ -248,6 +255,7 @@ en:
|
||||||
ignore_block: Ignore User's domain blocking
|
ignore_block: Ignore User's domain blocking
|
||||||
keyword: Keyword list or regular expression
|
keyword: Keyword list or regular expression
|
||||||
list_id: Target timeline
|
list_id: Target timeline
|
||||||
|
media_only: Media only
|
||||||
name: Name
|
name: Name
|
||||||
regexp: Use regular expressions for keywords
|
regexp: Use regular expressions for keywords
|
||||||
keyword_subscribes:
|
keyword_subscribes:
|
||||||
|
@ -255,6 +263,7 @@ en:
|
||||||
ignorecase: Case
|
ignorecase: Case
|
||||||
ignore_block: Block
|
ignore_block: Block
|
||||||
keyword: String
|
keyword: String
|
||||||
|
media_only: Media
|
||||||
name: Name
|
name: Name
|
||||||
regexp: Type
|
regexp: Type
|
||||||
timeline: Timeline
|
timeline: Timeline
|
||||||
|
|
|
@ -71,15 +71,18 @@ ja:
|
||||||
domain_subscribe:
|
domain_subscribe:
|
||||||
domain: 購読したいサーバのドメイン名を指定します
|
domain: 購読したいサーバのドメイン名を指定します
|
||||||
exclude_reblog: ブーストされた投稿を購読から除外します
|
exclude_reblog: ブーストされた投稿を購読から除外します
|
||||||
|
media_only: メディアが添付された投稿だけを対象にします
|
||||||
email_domain_block:
|
email_domain_block:
|
||||||
domain: メールアドレスのドメイン名および、名前解決したMXレコード、IPアドレスを指定できます。ユーザー登録時にこれらをチェックし、該当する場合はユーザー登録を拒否します。
|
domain: メールアドレスのドメイン名および、名前解決したMXレコード、IPアドレスを指定できます。ユーザー登録時にこれらをチェックし、該当する場合はユーザー登録を拒否します。
|
||||||
with_dns_records: 指定したドメインのDNSレコードを取得し、その結果もメールドメインブロックに登録されます
|
with_dns_records: 指定したドメインのDNSレコードを取得し、その結果もメールドメインブロックに登録されます
|
||||||
featured_tag:
|
featured_tag:
|
||||||
name: 'これらを使うといいかもしれません:'
|
name: 'これらを使うといいかもしれません:'
|
||||||
follow_tag:
|
follow_tag:
|
||||||
|
media_only: メディアが添付された投稿だけを対象にします
|
||||||
name: フォローしたいハッシュタグを '#' 抜きで指定します
|
name: フォローしたいハッシュタグを '#' 抜きで指定します
|
||||||
form_account_subscribe:
|
form_account_subscribe:
|
||||||
acct: 購読したいアカウントを username@domain 形式で指定します
|
acct: 購読したいアカウントを username@domain 形式で指定します
|
||||||
|
media_only: メディアが添付された投稿だけを対象にします
|
||||||
show_reblogs: ブーストされた投稿を購読に含めます
|
show_reblogs: ブーストされた投稿を購読に含めます
|
||||||
form_challenge:
|
form_challenge:
|
||||||
current_password: セキュリティ上重要なエリアにアクセスしています
|
current_password: セキュリティ上重要なエリアにアクセスしています
|
||||||
|
@ -99,6 +102,7 @@ ja:
|
||||||
exclude_keyword: カンマで区切って複数の除外するキーワードを並べます(または正規表現で指定します)
|
exclude_keyword: カンマで区切って複数の除外するキーワードを並べます(または正規表現で指定します)
|
||||||
ignore_block: ドメイン全体を非表示にしたまま、キーワードの購読を優先することができます
|
ignore_block: ドメイン全体を非表示にしたまま、キーワードの購読を優先することができます
|
||||||
keyword: カンマで区切って複数のキーワードを並べます(または正規表現で指定します)
|
keyword: カンマで区切って複数のキーワードを並べます(または正規表現で指定します)
|
||||||
|
media_only: メディアが添付された投稿だけを対象にします
|
||||||
name: オプションです
|
name: オプションです
|
||||||
rule:
|
rule:
|
||||||
text: ユーザーのためのルールや要件を記述してください。短くシンプルにしてください。
|
text: ユーザーのためのルールや要件を記述してください。短くシンプルにしてください。
|
||||||
|
@ -210,6 +214,7 @@ ja:
|
||||||
domain: ドメイン
|
domain: ドメイン
|
||||||
exclude_reblog: ブースト除外
|
exclude_reblog: ブースト除外
|
||||||
list_id: 対象タイムライン
|
list_id: 対象タイムライン
|
||||||
|
media_only: メディアのみ
|
||||||
reblog: ブースト
|
reblog: ブースト
|
||||||
timeline: タイムライン
|
timeline: タイムライン
|
||||||
email_domain_block:
|
email_domain_block:
|
||||||
|
@ -222,11 +227,13 @@ ja:
|
||||||
name: ハッシュタグ
|
name: ハッシュタグ
|
||||||
follow_tag:
|
follow_tag:
|
||||||
list_id: 対象タイムライン
|
list_id: 対象タイムライン
|
||||||
|
media_only: メディアのみ
|
||||||
name: ハッシュタグ
|
name: ハッシュタグ
|
||||||
timeline: タイムライン
|
timeline: タイムライン
|
||||||
form_account_subscribe:
|
form_account_subscribe:
|
||||||
acct: アカウント
|
acct: アカウント
|
||||||
list_id: 対象タイムライン
|
list_id: 対象タイムライン
|
||||||
|
media_only: メディアのみ
|
||||||
reblog: ブースト
|
reblog: ブースト
|
||||||
show_reblogs: ブーストを表示
|
show_reblogs: ブーストを表示
|
||||||
timeline: タイムライン
|
timeline: タイムライン
|
||||||
|
@ -251,6 +258,7 @@ ja:
|
||||||
ignorecase: 大文字と小文字を区別しない
|
ignorecase: 大文字と小文字を区別しない
|
||||||
ignore_block: ユーザーによるドメインブロックを無視する
|
ignore_block: ユーザーによるドメインブロックを無視する
|
||||||
keyword: キーワードまたは正規表現
|
keyword: キーワードまたは正規表現
|
||||||
|
media_only: メディアのみ
|
||||||
list_id: 対象タイムライン
|
list_id: 対象タイムライン
|
||||||
name: 名称
|
name: 名称
|
||||||
regexp: キーワードに正規表現を使う
|
regexp: キーワードに正規表現を使う
|
||||||
|
@ -259,6 +267,7 @@ ja:
|
||||||
ignorecase: 大小
|
ignorecase: 大小
|
||||||
ignore_block: ブロック
|
ignore_block: ブロック
|
||||||
keyword: 設定値
|
keyword: 設定値
|
||||||
|
media_only: メディア
|
||||||
name: 名称
|
name: 名称
|
||||||
regexp: 種別
|
regexp: 種別
|
||||||
timeline: タイムライン
|
timeline: タイムライン
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
require Rails.root.join('lib', 'mastodon', 'migration_helpers')
|
||||||
|
|
||||||
|
class AddMediaOnlyToAccountSubscribe < ActiveRecord::Migration[5.2]
|
||||||
|
include Mastodon::MigrationHelpers
|
||||||
|
|
||||||
|
disable_ddl_transaction!
|
||||||
|
|
||||||
|
def up
|
||||||
|
safety_assured do
|
||||||
|
add_column_with_default :account_subscribes, :media_only, :boolean, default: false, allow_null: false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def down
|
||||||
|
remove_column :account_subscribes, :media_only
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,17 @@
|
||||||
|
require Rails.root.join('lib', 'mastodon', 'migration_helpers')
|
||||||
|
|
||||||
|
class AddMediaOnlyToDomainSubscribe < ActiveRecord::Migration[5.2]
|
||||||
|
include Mastodon::MigrationHelpers
|
||||||
|
|
||||||
|
disable_ddl_transaction!
|
||||||
|
|
||||||
|
def up
|
||||||
|
safety_assured do
|
||||||
|
add_column_with_default :domain_subscribes, :media_only, :boolean, default: false, allow_null: false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def down
|
||||||
|
remove_column :domain_subscribes, :media_only
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,17 @@
|
||||||
|
require Rails.root.join('lib', 'mastodon', 'migration_helpers')
|
||||||
|
|
||||||
|
class AddMediaOnlyToKeywordSubscribe < ActiveRecord::Migration[5.2]
|
||||||
|
include Mastodon::MigrationHelpers
|
||||||
|
|
||||||
|
disable_ddl_transaction!
|
||||||
|
|
||||||
|
def up
|
||||||
|
safety_assured do
|
||||||
|
add_column_with_default :keyword_subscribes, :media_only, :boolean, default: false, allow_null: false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def down
|
||||||
|
remove_column :keyword_subscribes, :media_only
|
||||||
|
end
|
||||||
|
end
|
17
db/migrate/20201114013422_add_media_only_to_follow_tag.rb
Normal file
17
db/migrate/20201114013422_add_media_only_to_follow_tag.rb
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
require Rails.root.join('lib', 'mastodon', 'migration_helpers')
|
||||||
|
|
||||||
|
class AddMediaOnlyToFollowTag < ActiveRecord::Migration[5.2]
|
||||||
|
include Mastodon::MigrationHelpers
|
||||||
|
|
||||||
|
disable_ddl_transaction!
|
||||||
|
|
||||||
|
def up
|
||||||
|
safety_assured do
|
||||||
|
add_column_with_default :follow_tags, :media_only, :boolean, default: false, allow_null: false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def down
|
||||||
|
remove_column :follow_tags, :media_only
|
||||||
|
end
|
||||||
|
end
|
|
@ -139,6 +139,7 @@ ActiveRecord::Schema.define(version: 2021_08_08_071221) do
|
||||||
t.datetime "updated_at", null: false
|
t.datetime "updated_at", null: false
|
||||||
t.bigint "list_id"
|
t.bigint "list_id"
|
||||||
t.boolean "show_reblogs", default: true, null: false
|
t.boolean "show_reblogs", default: true, null: false
|
||||||
|
t.boolean "media_only", default: false, null: false
|
||||||
t.index ["account_id"], name: "index_account_subscribes_on_account_id"
|
t.index ["account_id"], name: "index_account_subscribes_on_account_id"
|
||||||
t.index ["list_id"], name: "index_account_subscribes_on_list_id"
|
t.index ["list_id"], name: "index_account_subscribes_on_list_id"
|
||||||
t.index ["target_account_id"], name: "index_account_subscribes_on_target_account_id"
|
t.index ["target_account_id"], name: "index_account_subscribes_on_target_account_id"
|
||||||
|
@ -419,6 +420,7 @@ ActiveRecord::Schema.define(version: 2021_08_08_071221) do
|
||||||
t.datetime "created_at", null: false
|
t.datetime "created_at", null: false
|
||||||
t.datetime "updated_at", null: false
|
t.datetime "updated_at", null: false
|
||||||
t.boolean "exclude_reblog", default: true
|
t.boolean "exclude_reblog", default: true
|
||||||
|
t.boolean "media_only", default: false, null: false
|
||||||
t.index ["account_id"], name: "index_domain_subscribes_on_account_id"
|
t.index ["account_id"], name: "index_domain_subscribes_on_account_id"
|
||||||
t.index ["list_id"], name: "index_domain_subscribes_on_list_id"
|
t.index ["list_id"], name: "index_domain_subscribes_on_list_id"
|
||||||
end
|
end
|
||||||
|
@ -529,6 +531,7 @@ ActiveRecord::Schema.define(version: 2021_08_08_071221) do
|
||||||
t.datetime "created_at", null: false
|
t.datetime "created_at", null: false
|
||||||
t.datetime "updated_at", null: false
|
t.datetime "updated_at", null: false
|
||||||
t.bigint "list_id"
|
t.bigint "list_id"
|
||||||
|
t.boolean "media_only", default: false, null: false
|
||||||
t.index ["account_id"], name: "index_follow_tags_on_account_id"
|
t.index ["account_id"], name: "index_follow_tags_on_account_id"
|
||||||
t.index ["list_id"], name: "index_follow_tags_on_list_id"
|
t.index ["list_id"], name: "index_follow_tags_on_list_id"
|
||||||
t.index ["tag_id"], name: "index_follow_tags_on_tag_id"
|
t.index ["tag_id"], name: "index_follow_tags_on_tag_id"
|
||||||
|
@ -542,7 +545,6 @@ ActiveRecord::Schema.define(version: 2021_08_08_071221) do
|
||||||
t.boolean "show_reblogs", default: true, null: false
|
t.boolean "show_reblogs", default: true, null: false
|
||||||
t.string "uri"
|
t.string "uri"
|
||||||
t.boolean "notify", default: false, null: false
|
t.boolean "notify", default: false, null: false
|
||||||
t.boolean "private", default: true, null: false
|
|
||||||
t.boolean "delivery", default: true, null: false
|
t.boolean "delivery", default: true, null: false
|
||||||
t.index ["account_id", "target_account_id"], name: "index_follows_on_account_id_and_target_account_id", unique: true
|
t.index ["account_id", "target_account_id"], name: "index_follows_on_account_id_and_target_account_id", unique: true
|
||||||
t.index ["target_account_id"], name: "index_follows_on_target_account_id"
|
t.index ["target_account_id"], name: "index_follows_on_target_account_id"
|
||||||
|
@ -605,6 +607,7 @@ ActiveRecord::Schema.define(version: 2021_08_08_071221) do
|
||||||
t.boolean "disabled", default: false
|
t.boolean "disabled", default: false
|
||||||
t.string "exclude_keyword", default: "", null: false
|
t.string "exclude_keyword", default: "", null: false
|
||||||
t.bigint "list_id"
|
t.bigint "list_id"
|
||||||
|
t.boolean "media_only", default: false, null: false
|
||||||
t.index ["account_id"], name: "index_keyword_subscribes_on_account_id"
|
t.index ["account_id"], name: "index_keyword_subscribes_on_account_id"
|
||||||
t.index ["list_id"], name: "index_keyword_subscribes_on_list_id"
|
t.index ["list_id"], name: "index_keyword_subscribes_on_list_id"
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue