Add option to be notified when a followed user posts (#13546)

* Add bell button

Fix #4890

* Remove duplicate type from post-deployment migration

* Fix legacy class type mappings

* Improve query performance with better index

* Fix validation

* Remove redundant index from notifications
This commit is contained in:
Eugen Rochko 2020-09-18 17:26:45 +02:00 committed by GitHub
parent 75e4bd9413
commit 974b1b79ce
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
42 changed files with 330 additions and 112 deletions

View file

@ -29,7 +29,7 @@ class FavouriteService < BaseService
status = favourite.status
if status.account.local?
NotifyService.new.call(status.account, favourite)
NotifyService.new.call(status.account, :favourite, favourite)
elsif status.account.activitypub?
ActivityPub::DeliveryWorker.perform_async(build_json(favourite), favourite.account_id, status.account.inbox_url)
end

View file

@ -9,12 +9,13 @@ class FollowService < BaseService
# @param [String, Account] uri User URI to follow in the form of username@domain (or account record)
# @param [Hash] options
# @option [Boolean] :reblogs Whether or not to show reblogs, defaults to true
# @option [Boolean] :notify Whether to create notifications about new posts, defaults to false
# @option [Boolean] :bypass_locked
# @option [Boolean] :with_rate_limit
def call(source_account, target_account, options = {})
@source_account = source_account
@target_account = ResolveAccountService.new.call(target_account, skip_webfinger: true)
@options = { reblogs: true, bypass_locked: false, with_rate_limit: false }.merge(options)
@options = { bypass_locked: false, with_rate_limit: false }.merge(options)
raise ActiveRecord::RecordNotFound if following_not_possible?
raise Mastodon::NotPermittedError if following_not_allowed?
@ -45,18 +46,18 @@ class FollowService < BaseService
end
def change_follow_options!
@source_account.follow!(@target_account, reblogs: @options[:reblogs])
@source_account.follow!(@target_account, reblogs: @options[:reblogs], notify: @options[:notify])
end
def change_follow_request_options!
@source_account.request_follow!(@target_account, reblogs: @options[:reblogs])
@source_account.request_follow!(@target_account, reblogs: @options[:reblogs], notify: @options[:notify])
end
def request_follow!
follow_request = @source_account.request_follow!(@target_account, reblogs: @options[:reblogs], rate_limit: @options[:with_rate_limit])
follow_request = @source_account.request_follow!(@target_account, reblogs: @options[:reblogs], notify: @options[:notify], rate_limit: @options[:with_rate_limit])
if @target_account.local?
LocalNotificationWorker.perform_async(@target_account.id, follow_request.id, follow_request.class.name)
LocalNotificationWorker.perform_async(@target_account.id, follow_request.id, follow_request.class.name, :follow_request)
elsif @target_account.activitypub?
ActivityPub::DeliveryWorker.perform_async(build_json(follow_request), @source_account.id, @target_account.inbox_url)
end
@ -65,9 +66,9 @@ class FollowService < BaseService
end
def direct_follow!
follow = @source_account.follow!(@target_account, reblogs: @options[:reblogs], rate_limit: @options[:with_rate_limit])
follow = @source_account.follow!(@target_account, reblogs: @options[:reblogs], notify: @options[:notify], rate_limit: @options[:with_rate_limit])
LocalNotificationWorker.perform_async(@target_account.id, follow.id, follow.class.name)
LocalNotificationWorker.perform_async(@target_account.id, follow.id, follow.class.name, :follow)
MergeWorker.perform_async(@target_account.id, @source_account.id)
follow

View file

@ -25,7 +25,7 @@ class ImportService < BaseService
def import_follows!
parse_import_data!(['Account address'])
import_relationships!('follow', 'unfollow', @account.following, follow_limit, reblogs: 'Show boosts')
import_relationships!('follow', 'unfollow', @account.following, follow_limit, reblogs: { header: 'Show boosts', default: true })
end
def import_blocks!
@ -35,7 +35,7 @@ class ImportService < BaseService
def import_mutes!
parse_import_data!(['Account address'])
import_relationships!('mute', 'unmute', @account.muting, ROWS_PROCESSING_LIMIT, notifications: 'Hide notifications')
import_relationships!('mute', 'unmute', @account.muting, ROWS_PROCESSING_LIMIT, notifications: { header: 'Hide notifications', default: true })
end
def import_domain_blocks!
@ -65,7 +65,7 @@ class ImportService < BaseService
def import_relationships!(action, undo_action, overwrite_scope, limit, extra_fields = {})
local_domain_suffix = "@#{Rails.configuration.x.local_domain}"
items = @data.take(limit).map { |row| [row['Account address']&.strip&.delete_suffix(local_domain_suffix), Hash[extra_fields.map { |key, header| [key, row[header]&.strip] }]] }.reject { |(id, _)| id.blank? }
items = @data.take(limit).map { |row| [row['Account address']&.strip&.delete_suffix(local_domain_suffix), Hash[extra_fields.map { |key, field_settings| [key, row[field_settings[:header]]&.strip || field_settings[:default]] }]] }.reject { |(id, _)| id.blank? }
if @import.overwrite?
presence_hash = items.each_with_object({}) { |(id, extra), mapping| mapping[id] = [true, extra] }

View file

@ -1,10 +1,10 @@
# frozen_string_literal: true
class NotifyService < BaseService
def call(recipient, activity)
def call(recipient, type, activity)
@recipient = recipient
@activity = activity
@notification = Notification.new(account: @recipient, activity: @activity)
@notification = Notification.new(account: @recipient, type: type, activity: @activity)
return if recipient.user.nil? || blocked?
@ -22,6 +22,10 @@ class NotifyService < BaseService
FeedManager.instance.filter?(:mentions, @notification.mention.status, @recipient)
end
def blocked_status?
false
end
def blocked_favourite?
false
end

View file

@ -58,7 +58,7 @@ class ProcessMentionsService < BaseService
mentioned_account = mention.account
if mentioned_account.local?
LocalNotificationWorker.perform_async(mentioned_account.id, mention.id, mention.class.name)
LocalNotificationWorker.perform_async(mentioned_account.id, mention.id, mention.class.name, :mention)
elsif mentioned_account.activitypub?
ActivityPub::DeliveryWorker.perform_async(activitypub_json, mention.status.account_id, mentioned_account.inbox_url)
end

View file

@ -45,7 +45,7 @@ class ReblogService < BaseService
reblogged_status = reblog.reblog
if reblogged_status.account.local?
LocalNotificationWorker.perform_async(reblogged_status.account_id, reblog.id, reblog.class.name)
LocalNotificationWorker.perform_async(reblogged_status.account_id, reblog.id, reblog.class.name, :reblog)
elsif reblogged_status.account.activitypub? && !reblogged_status.account.following?(reblog.account)
ActivityPub::DeliveryWorker.perform_async(build_json(reblog), reblog.account_id, reblogged_status.account.inbox_url)
end