From c30d4b5162f3b3f2ee5643205e3ae3ce7204e984 Mon Sep 17 00:00:00 2001 From: KMY Date: Wed, 26 Jul 2023 11:33:28 +0900 Subject: [PATCH] Change emoji reaction duplication check --- app/lib/activitypub/activity/like.rb | 13 +++++++++++-- app/models/emoji_reaction.rb | 1 - app/services/emoji_react_service.rb | 18 +++++++++++------- 3 files changed, 22 insertions(+), 10 deletions(-) diff --git a/app/lib/activitypub/activity/like.rb b/app/lib/activitypub/activity/like.rb index 3f98591e99..c552403346 100644 --- a/app/lib/activitypub/activity/like.rb +++ b/app/lib/activitypub/activity/like.rb @@ -1,6 +1,9 @@ # frozen_string_literal: true class ActivityPub::Activity::Like < ActivityPub::Activity + include Redisable + include Lockable + def perform @original_status = status_from_uri(object_uri) @@ -44,9 +47,15 @@ class ActivityPub::Activity::Like < ActivityPub::Activity Trends.statuses.register(@original_status) end - return if EmojiReaction.where(account: @account, status: @original_status).count >= EmojiReaction::EMOJI_REACTION_PER_ACCOUNT_LIMIT + reaction = nil + + with_redis_lock("emoji_reaction:#{@original_status.id}") do + return if EmojiReaction.where(account: @account, status: @original_status).count >= EmojiReaction::EMOJI_REACTION_PER_ACCOUNT_LIMIT + return if EmojiReaction.find_by(account: @account, status: @original_status, name: shortcode) + + reaction = @original_status.emoji_reactions.create!(account: @account, name: shortcode, custom_emoji: emoji, uri: @json['id']) + end - reaction = @original_status.emoji_reactions.create!(account: @account, name: shortcode, custom_emoji: emoji, uri: @json['id']) write_stream(reaction) if @original_status.account.local? diff --git a/app/models/emoji_reaction.rb b/app/models/emoji_reaction.rb index b3cc11cf32..bbe00a2c54 100644 --- a/app/models/emoji_reaction.rb +++ b/app/models/emoji_reaction.rb @@ -28,7 +28,6 @@ class EmojiReaction < ApplicationRecord has_one :notification, as: :activity, dependent: :destroy - validate :status_same_emoji_reaction validate :status_emoji_reactions_count validates_with EmojiReactionValidator diff --git a/app/services/emoji_react_service.rb b/app/services/emoji_react_service.rb index 325897e198..7be550c391 100644 --- a/app/services/emoji_react_service.rb +++ b/app/services/emoji_react_service.rb @@ -4,6 +4,7 @@ class EmojiReactService < BaseService include Authorization include Payloadable include Redisable + include Lockable # React a status with emoji and notify remote user # @param [Account] account @@ -14,17 +15,20 @@ class EmojiReactService < BaseService status = status.reblog if status.reblog? && !status.reblog.nil? authorize_with account, status, :emoji_reaction? - emoji_reaction = EmojiReaction.find_by(account: account, status: status, name: name) + emoji_reaction = nil - return emoji_reaction unless emoji_reaction.nil? + with_redis_lock("emoji_reaction:#{status.id}") do + emoji_reaction = EmojiReaction.find_by(account: account, status: status, name: name) + raise Mastodon::ValidationError, I18n.t('reactions.errors.duplication') unless emoji_reaction.nil? - shortcode, domain = name.split('@') + shortcode, domain = name.split('@') + custom_emoji = CustomEmoji.find_by(shortcode: shortcode, domain: domain) + emoji_reaction = EmojiReaction.create!(account: account, status: status, name: shortcode, custom_emoji: custom_emoji) - custom_emoji = CustomEmoji.find_by(shortcode: shortcode, domain: domain) + status.touch # rubocop:disable Rails/SkipsModelValidations + end - emoji_reaction = EmojiReaction.create!(account: account, status: status, name: shortcode, custom_emoji: custom_emoji) - - status.touch # rubocop:disable Rails/SkipsModelValidations + raise Mastodon::ValidationError, I18n.t('reactions.errors.duplication') if emoji_reaction.nil? Trends.statuses.register(status)