スタンプ機能のリファクタリング、投稿の反応者へも配送 (#140)
This commit is contained in:
parent
9b1821d001
commit
d62a135806
3 changed files with 87 additions and 47 deletions
|
@ -25,6 +25,10 @@ class StatusReachFinder
|
||||||
(reached_account_inboxes_for_friend + followers_inboxes_for_friend + friend_inboxes).uniq
|
(reached_account_inboxes_for_friend + followers_inboxes_for_friend + friend_inboxes).uniq
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def all_inboxes
|
||||||
|
(inboxes + inboxes_for_misskey + inboxes_for_friend).uniq
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def reached_account_inboxes
|
def reached_account_inboxes
|
||||||
|
|
|
@ -16,95 +16,81 @@ class EmojiReactService < BaseService
|
||||||
authorize_with account, status, :emoji_reaction?
|
authorize_with account, status, :emoji_reaction?
|
||||||
@status = status
|
@status = status
|
||||||
|
|
||||||
emoji_reaction = nil
|
|
||||||
|
|
||||||
with_redis_lock("emoji_reaction:#{status.id}") do
|
with_redis_lock("emoji_reaction:#{status.id}") do
|
||||||
emoji_reaction = EmojiReaction.find_by(account: account, status: status, name: name)
|
@emoji_reaction = EmojiReaction.find_by(account: account, status: status, name: name)
|
||||||
raise Mastodon::ValidationError, I18n.t('reactions.errors.duplication') unless emoji_reaction.nil?
|
raise Mastodon::ValidationError, I18n.t('reactions.errors.duplication') unless @emoji_reaction.nil?
|
||||||
|
|
||||||
shortcode, domain = name.split('@')
|
shortcode, domain = name.split('@')
|
||||||
domain = nil if TagManager.instance.local_domain?(domain)
|
domain = nil if TagManager.instance.local_domain?(domain)
|
||||||
custom_emoji = CustomEmoji.find_by(shortcode: shortcode, domain: domain)
|
custom_emoji = CustomEmoji.find_by(shortcode: shortcode, domain: domain)
|
||||||
return if domain.present? && !EmojiReaction.exists?(status: status, custom_emoji: custom_emoji)
|
return if domain.present? && !EmojiReaction.exists?(status: status, custom_emoji: custom_emoji)
|
||||||
|
|
||||||
emoji_reaction = EmojiReaction.create!(account: account, status: status, name: shortcode, custom_emoji: custom_emoji)
|
@emoji_reaction = EmojiReaction.create!(account: account, status: status, name: shortcode, custom_emoji: custom_emoji)
|
||||||
|
|
||||||
status.touch # rubocop:disable Rails/SkipsModelValidations
|
status.touch # rubocop:disable Rails/SkipsModelValidations
|
||||||
end
|
end
|
||||||
|
|
||||||
raise Mastodon::ValidationError, I18n.t('reactions.errors.duplication') if emoji_reaction.nil?
|
raise Mastodon::ValidationError, I18n.t('reactions.errors.duplication') if @emoji_reaction.nil?
|
||||||
|
|
||||||
Trends.statuses.register(status)
|
Trends.statuses.register(status)
|
||||||
|
|
||||||
create_notification(emoji_reaction)
|
create_notification
|
||||||
notify_to_followers(emoji_reaction)
|
notify_to_followers
|
||||||
bump_potential_friendship(account, status)
|
bump_potential_friendship!
|
||||||
write_stream(emoji_reaction)
|
write_stream!
|
||||||
relay_for_emoji_reaction!(emoji_reaction)
|
|
||||||
relay_friend_for_emoji_reaction!(emoji_reaction)
|
|
||||||
|
|
||||||
emoji_reaction
|
@emoji_reaction
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def create_notification(emoji_reaction)
|
def create_notification
|
||||||
status = emoji_reaction.status
|
status = @emoji_reaction.status
|
||||||
|
|
||||||
if status.account.local?
|
if status.account.local?
|
||||||
if status.account.user&.setting_enable_emoji_reaction
|
if status.account.user&.setting_enable_emoji_reaction
|
||||||
LocalNotificationWorker.perform_async(status.account_id, emoji_reaction.id, 'EmojiReaction', 'reaction') if status.account.user&.setting_emoji_reaction_streaming_notify_impl2
|
LocalNotificationWorker.perform_async(status.account_id, @emoji_reaction.id, 'EmojiReaction', 'reaction') if status.account.user&.setting_emoji_reaction_streaming_notify_impl2
|
||||||
LocalNotificationWorker.perform_async(status.account_id, emoji_reaction.id, 'EmojiReaction', 'emoji_reaction')
|
LocalNotificationWorker.perform_async(status.account_id, @emoji_reaction.id, 'EmojiReaction', 'emoji_reaction')
|
||||||
end
|
end
|
||||||
elsif status.account.activitypub?
|
elsif status.account.activitypub?
|
||||||
ActivityPub::DeliveryWorker.perform_async(build_json(emoji_reaction), emoji_reaction.account_id, status.account.inbox_url)
|
ActivityPub::DeliveryWorker.perform_async(payload, @emoji_reaction.account_id, status.account.inbox_url)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def notify_to_followers(emoji_reaction)
|
def notify_to_followers
|
||||||
status = emoji_reaction.status
|
status = @emoji_reaction.status
|
||||||
|
|
||||||
return unless status.account.local?
|
return unless status.account.local?
|
||||||
|
|
||||||
ActivityPub::RawDistributionWorker.perform_async(build_json(emoji_reaction), status.account_id)
|
ActivityPub::DeliveryWorker.push_bulk(inboxes, limit: 1_000) do |inbox_url|
|
||||||
|
[payload, @status.account.id, inbox_url]
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def write_stream(emoji_reaction)
|
def inboxes
|
||||||
emoji_group = emoji_reaction.status.emoji_reactions_grouped_by_name(nil, force: true)
|
StatusReachFinder.new(@status).all_inboxes
|
||||||
.find { |reaction_group| reaction_group['name'] == emoji_reaction.name && (!reaction_group.key?(:domain) || reaction_group['domain'] == emoji_reaction.custom_emoji&.domain) }
|
|
||||||
emoji_group['status_id'] = emoji_reaction.status_id.to_s
|
|
||||||
DeliveryEmojiReactionWorker.perform_async(render_emoji_reaction(emoji_group), emoji_reaction.status_id, emoji_reaction.account_id)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def bump_potential_friendship(account, status)
|
def write_stream!
|
||||||
|
emoji_group = @emoji_reaction.status.emoji_reactions_grouped_by_name(nil, force: true)
|
||||||
|
.find { |reaction_group| reaction_group['name'] == @emoji_reaction.name && (!reaction_group.key?(:domain) || reaction_group['domain'] == @emoji_reaction.custom_emoji&.domain) }
|
||||||
|
emoji_group['status_id'] = @emoji_reaction.status_id.to_s
|
||||||
|
DeliveryEmojiReactionWorker.perform_async(render_emoji_reaction(emoji_group), @emoji_reaction.status_id, @emoji_reaction.account_id)
|
||||||
|
end
|
||||||
|
|
||||||
|
def bump_potential_friendship!
|
||||||
ActivityTracker.increment('activity:interactions')
|
ActivityTracker.increment('activity:interactions')
|
||||||
return if account.following?(status.account_id)
|
return if @emoji_reaction.account.following?(@emoji_reaction.status.account_id)
|
||||||
|
|
||||||
PotentialFriendshipTracker.record(account.id, status.account_id, :emoji_reaction)
|
PotentialFriendshipTracker.record(@emoji_reaction.account.id, @emoji_reaction.status.account_id, :emoji_reaction)
|
||||||
end
|
end
|
||||||
|
|
||||||
def build_json(emoji_reaction)
|
def payload
|
||||||
@build_json = Oj.dump(serialize_payload(emoji_reaction, ActivityPub::EmojiReactionSerializer, signer: emoji_reaction.account))
|
@payload = Oj.dump(serialize_payload(@emoji_reaction, ActivityPub::EmojiReactionSerializer, signer: @emoji_reaction.account))
|
||||||
end
|
end
|
||||||
|
|
||||||
def render_emoji_reaction(emoji_group)
|
def render_emoji_reaction(emoji_group)
|
||||||
# @rendered_emoji_reaction ||= InlineRenderer.render(HashObject.new(emoji_group), nil, :emoji_reaction)
|
# @rendered_emoji_reaction ||= InlineRenderer.render(HashObject.new(emoji_group), nil, :emoji_reaction)
|
||||||
@render_emoji_reaction ||= Oj.dump(event: :emoji_reaction, payload: emoji_group.to_json)
|
@render_emoji_reaction ||= Oj.dump(event: :emoji_reaction, payload: emoji_group.to_json)
|
||||||
end
|
end
|
||||||
|
|
||||||
def relay_for_emoji_reaction!(emoji_reaction)
|
|
||||||
return unless @status.local? && @status.public_visibility?
|
|
||||||
|
|
||||||
ActivityPub::DeliveryWorker.push_bulk(Relay.enabled.pluck(:inbox_url)) do |inbox_url|
|
|
||||||
[build_json(emoji_reaction), @status.account.id, inbox_url]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def relay_friend_for_emoji_reaction!(emoji_reaction)
|
|
||||||
return unless @status.local? && @status.distributable_friend?
|
|
||||||
|
|
||||||
ActivityPub::DeliveryWorker.push_bulk(FriendDomain.distributables.pluck(:inbox_url)) do |inbox_url|
|
|
||||||
[build_json(emoji_reaction), @status.account.id, inbox_url]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -138,4 +138,54 @@ RSpec.describe EmojiReactService, type: :service do
|
||||||
expect(subject.first.custom_emoji.domain).to eq 'foo.bar'
|
expect(subject.first.custom_emoji.domain).to eq 'foo.bar'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'when has remote followers' do
|
||||||
|
let!(:bob) { Fabricate(:account, domain: 'foo.bar', uri: 'https://foo.bar/actor', inbox_url: 'https://foo.bar/inbox', protocol: 'activitypub') }
|
||||||
|
|
||||||
|
before do
|
||||||
|
bob.follow!(author)
|
||||||
|
stub_request(:post, 'https://foo.bar/inbox')
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'react with emoji' do
|
||||||
|
expect(subject.count).to eq 1
|
||||||
|
expect(a_request(:post, 'https://foo.bar/inbox').with(body: hash_including({
|
||||||
|
type: 'Like',
|
||||||
|
actor: ActivityPub::TagManager.instance.uri_for(sender),
|
||||||
|
content: '😀',
|
||||||
|
}))).to have_been_made.once
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when has relay server' do
|
||||||
|
before do
|
||||||
|
Fabricate(:relay, inbox_url: 'https://foo.bar/inbox', state: :accepted)
|
||||||
|
stub_request(:post, 'https://foo.bar/inbox')
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'react with emoji' do
|
||||||
|
expect(subject.count).to eq 1
|
||||||
|
expect(a_request(:post, 'https://foo.bar/inbox').with(body: hash_including({
|
||||||
|
type: 'Like',
|
||||||
|
actor: ActivityPub::TagManager.instance.uri_for(sender),
|
||||||
|
content: '😀',
|
||||||
|
}))).to have_been_made.once
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when has friend server' do
|
||||||
|
before do
|
||||||
|
Fabricate(:friend_domain, inbox_url: 'https://foo.bar/inbox', active_state: :accepted, pseudo_relay: true)
|
||||||
|
stub_request(:post, 'https://foo.bar/inbox')
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'react with emoji' do
|
||||||
|
expect(subject.count).to eq 1
|
||||||
|
expect(a_request(:post, 'https://foo.bar/inbox').with(body: hash_including({
|
||||||
|
type: 'Like',
|
||||||
|
actor: ActivityPub::TagManager.instance.uri_for(sender),
|
||||||
|
content: '😀',
|
||||||
|
}))).to have_been_made.once
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue