From d6162ada0469d57c1ca60fd846d4dd532a0b9e37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?KMY=EF=BC=88=E9=9B=AA=E3=81=82=E3=81=99=E3=81=8B=EF=BC=89?= Date: Thu, 12 Oct 2023 20:06:21 +0900 Subject: [PATCH 1/9] =?UTF-8?q?Fix:=20#89=20NodeInfo=E5=90=91=E3=81=91?= =?UTF-8?q?=E3=81=AE=E6=A9=9F=E8=83=BD=E4=B8=80=E8=A6=A7=E8=A1=A8=E3=82=92?= =?UTF-8?q?=E4=BD=9C=E6=88=90=E3=81=97=E3=81=A6=E5=8C=BA=E5=88=A5=20(#103)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/helpers/kmyblue_capabilities_helper.rb | 25 +++++++++++++++++++ app/serializers/nodeinfo/serializer.rb | 2 +- spec/serializers/nodeinfo/serializer_spec.rb | 5 ++++ .../rest/instance_serializer_spec.rb | 4 +++ 4 files changed, 35 insertions(+), 1 deletion(-) diff --git a/app/helpers/kmyblue_capabilities_helper.rb b/app/helpers/kmyblue_capabilities_helper.rb index 8653a3f9da..455561a597 100644 --- a/app/helpers/kmyblue_capabilities_helper.rb +++ b/app/helpers/kmyblue_capabilities_helper.rb @@ -30,4 +30,29 @@ module KmyblueCapabilitiesHelper capabilities end + + def capabilities_for_nodeinfo + capabilities = %i( + wide_emoji + status_reference + quote + kmyblue_quote + searchability + kmyblue_searchability + visibility_mutual + visibility_limited + kmyblue_antenna + kmyblue_bookmark_category + kmyblue_searchability_limited + kmyblue_circle_history + ) + + capabilities << :full_text_search if Chewy.enabled? + if Setting.enable_emoji_reaction + capabilities << :emoji_reaction + capabilities << :enable_wide_emoji_reaction + end + + capabilities + end end diff --git a/app/serializers/nodeinfo/serializer.rb b/app/serializers/nodeinfo/serializer.rb index 3555f0bd8d..83d63bb397 100644 --- a/app/serializers/nodeinfo/serializer.rb +++ b/app/serializers/nodeinfo/serializer.rb @@ -40,7 +40,7 @@ class NodeInfo::Serializer < ActiveModel::Serializer def metadata { - features: fedibird_capabilities, + features: capabilities_for_nodeinfo, } end diff --git a/spec/serializers/nodeinfo/serializer_spec.rb b/spec/serializers/nodeinfo/serializer_spec.rb index c43b0b569f..8352a44143 100644 --- a/spec/serializers/nodeinfo/serializer_spec.rb +++ b/spec/serializers/nodeinfo/serializer_spec.rb @@ -28,5 +28,10 @@ describe NodeInfo::Serializer do # rubocop:disable RSpec/FilePath it 'returns features' do expect(serialization['metadata']['features']).to include 'emoji_reaction' end + + it 'returns nodeinfo own features' do + expect(serialization['metadata']['features']).to include 'quote' + expect(serialization['metadata']['features']).to_not include 'kmyblue_markdown' + end end end diff --git a/spec/serializers/rest/instance_serializer_spec.rb b/spec/serializers/rest/instance_serializer_spec.rb index a9a3259aa8..4b33d15daa 100644 --- a/spec/serializers/rest/instance_serializer_spec.rb +++ b/spec/serializers/rest/instance_serializer_spec.rb @@ -22,5 +22,9 @@ describe REST::InstanceSerializer do it 'returns fedibird_capabilities' do expect(serialization['fedibird_capabilities']).to include 'emoji_reaction' end + + it 'returns api own fedibird_capabilities' do + expect(serialization['fedibird_capabilities']).to include 'kmyblue_markdown' + end end end From fc452f7740327018cbe5b2823a7fab485fe2ed35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?KMY=EF=BC=88=E9=9B=AA=E3=81=82=E3=81=99=E3=81=8B=EF=BC=89?= Date: Thu, 12 Oct 2023 20:06:33 +0900 Subject: [PATCH 2/9] =?UTF-8?q?Fix:=20#83=20=E3=83=95=E3=83=AC=E3=83=B3?= =?UTF-8?q?=E3=83=89=E3=82=B5=E3=83=BC=E3=83=90=E3=83=BC=E3=81=A7=E3=81=AE?= =?UTF-8?q?=E5=85=A8=E6=8A=95=E7=A8=BF=E9=85=8D=E9=80=81=E3=81=A7=E3=80=81?= =?UTF-8?q?=E3=82=A2=E3=82=AB=E3=82=A6=E3=83=B3=E3=83=88=E3=83=89=E3=83=A1?= =?UTF-8?q?=E3=82=A4=E3=83=B3=E3=83=96=E3=83=AD=E3=83=83=E3=82=AF=E3=81=8C?= =?UTF-8?q?=E7=84=A1=E8=A6=96=E3=81=95=E3=82=8C=E3=82=8B=E5=95=8F=E9=A1=8C?= =?UTF-8?q?=20(#102)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/lib/status_reach_finder.rb | 4 ++-- spec/lib/status_reach_finder_spec.rb | 12 ++++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/app/lib/status_reach_finder.rb b/app/lib/status_reach_finder.rb index 5a33418fab..22b0d94ff6 100644 --- a/app/lib/status_reach_finder.rb +++ b/app/lib/status_reach_finder.rb @@ -147,7 +147,7 @@ class StatusReachFinder def friend_inboxes if @status.public_visibility? || @status.public_unlisted_visibility? || (@status.unlisted_visibility? && (@status.public_searchability? || @status.public_unlisted_searchability?)) - DeliveryFailureTracker.without_unavailable(FriendDomain.distributables.where(delivery_local: true).pluck(:inbox_url)) + DeliveryFailureTracker.without_unavailable(FriendDomain.distributables.where(delivery_local: true).where.not(domain: AccountDomainBlock.where(account: @status.account).select(:domain)).pluck(:inbox_url)) else [] end @@ -155,7 +155,7 @@ class StatusReachFinder def nolocal_friend_inboxes if @status.public_visibility? - DeliveryFailureTracker.without_unavailable(FriendDomain.distributables.where(delivery_local: false).pluck(:inbox_url)) + DeliveryFailureTracker.without_unavailable(FriendDomain.distributables.where(delivery_local: false).where.not(domain: AccountDomainBlock.where(account: @status.account).select(:domain)).pluck(:inbox_url)) else [] end diff --git a/spec/lib/status_reach_finder_spec.rb b/spec/lib/status_reach_finder_spec.rb index 2d8e075d5b..8b333de0c4 100644 --- a/spec/lib/status_reach_finder_spec.rb +++ b/spec/lib/status_reach_finder_spec.rb @@ -239,6 +239,18 @@ describe StatusReachFinder do expect(subject.inboxes_for_friend).to_not include 'https://foo.bar/inbox' end end + + context 'when distributable but domain blocked by account' do + before do + Fabricate(:account_domain_block, account: alice, domain: 'foo.bar') + Fabricate(:friend_domain, domain: 'foo.bar', inbox_url: 'https://foo.bar/inbox', passive_state: :accepted, pseudo_relay: true) + end + + it 'send status' do + expect(subject.inboxes).to_not include 'https://foo.bar/inbox' + expect(subject.inboxes_for_friend).to_not include 'https://foo.bar/inbox' + end + end end context 'when it contains distributable friend server' do From eea84d476e3555be8e4bd0464a551ad4ac8f6fc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?KMY=EF=BC=88=E9=9B=AA=E3=81=82=E3=81=99=E3=81=8B=EF=BC=89?= Date: Fri, 13 Oct 2023 18:15:47 +0900 Subject: [PATCH 3/9] Fix when unfollow a tag, my post also disappears from the home timeline (#27391) --- app/lib/feed_manager.rb | 1 + spec/lib/feed_manager_spec.rb | 38 +++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/app/lib/feed_manager.rb b/app/lib/feed_manager.rb index 924884d39d..13b33bcbbf 100644 --- a/app/lib/feed_manager.rb +++ b/app/lib/feed_manager.rb @@ -207,6 +207,7 @@ class FeedManager # also tagged with another followed hashtag or from a followed user scope = from_tag.statuses .where(id: timeline_status_ids) + .where.not(account: into_account) .where.not(account: into_account.following) .tagged_with_none(TagFollow.where(account: into_account).pluck(:tag_id)) diff --git a/spec/lib/feed_manager_spec.rb b/spec/lib/feed_manager_spec.rb index d2e5da6b92..f5a3367b2b 100644 --- a/spec/lib/feed_manager_spec.rb +++ b/spec/lib/feed_manager_spec.rb @@ -562,6 +562,44 @@ RSpec.describe FeedManager do end end + describe '#unmerge_tag_from_home' do + let(:receiver) { Fabricate(:account) } + let(:tag) { Fabricate(:tag) } + + it 'leaves a tagged status' do + status = Fabricate(:status) + status.tags << tag + described_class.instance.push_to_home(receiver, status) + + described_class.instance.unmerge_tag_from_home(tag, receiver) + + expect(redis.zrange("feed:home:#{receiver.id}", 0, -1)).to_not include(status.id.to_s) + end + + it 'remains a tagged status written by receiver\'s followee' do + followee = Fabricate(:account) + receiver.follow!(followee) + + status = Fabricate(:status, account: followee) + status.tags << tag + described_class.instance.push_to_home(receiver, status) + + described_class.instance.unmerge_tag_from_home(tag, receiver) + + expect(redis.zrange("feed:home:#{receiver.id}", 0, -1)).to include(status.id.to_s) + end + + it 'remains a tagged status written by receiver' do + status = Fabricate(:status, account: receiver) + status.tags << tag + described_class.instance.push_to_home(receiver, status) + + described_class.instance.unmerge_tag_from_home(tag, receiver) + + expect(redis.zrange("feed:home:#{receiver.id}", 0, -1)).to include(status.id.to_s) + end + end + describe '#clear_from_home' do let(:account) { Fabricate(:account) } let(:followed_account) { Fabricate(:account) } From 6b4fc4a9dc1e3d7bb30800bc967002694bdd77ff Mon Sep 17 00:00:00 2001 From: KMY Date: Fri, 13 Oct 2023 18:37:43 +0900 Subject: [PATCH 4/9] =?UTF-8?q?Change:=20#82=20=E3=83=95=E3=83=AC=E3=83=B3?= =?UTF-8?q?=E3=83=89=E7=94=B3=E8=AB=8B=E6=99=82=E3=80=81=E8=87=AA=E5=88=86?= =?UTF-8?q?=E3=81=AE=E3=82=B5=E3=83=BC=E3=83=90=E3=83=BC=E3=81=AEInbox=20U?= =?UTF-8?q?RL=E3=82=92=E4=BC=9D=E3=81=88=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/lib/activitypub/activity/follow.rb | 2 +- app/models/friend_domain.rb | 11 +++++------ spec/lib/activitypub/activity/follow_spec.rb | 20 ++++++++++++++++++++ spec/models/friend_domain_spec.rb | 1 + 4 files changed, 27 insertions(+), 7 deletions(-) diff --git a/app/lib/activitypub/activity/follow.rb b/app/lib/activitypub/activity/follow.rb index f5a0250163..fdded98440 100644 --- a/app/lib/activitypub/activity/follow.rb +++ b/app/lib/activitypub/activity/follow.rb @@ -53,7 +53,7 @@ class ActivityPub::Activity::Follow < ActivityPub::Activity friend.update!(passive_state: :pending, active_state: :idle, passive_follow_activity_id: @json['id']) else @friend = FriendDomain.new(domain: @account.domain, passive_state: :pending, passive_follow_activity_id: @json['id']) - @friend.initialize_inbox_url! + @friend.inbox_url = @json['inboxUrl'].presence || @friend.default_inbox_url @friend.save! end diff --git a/app/models/friend_domain.rb b/app/models/friend_domain.rb index 28cc59b334..0842500033 100644 --- a/app/models/friend_domain.rb +++ b/app/models/friend_domain.rb @@ -93,16 +93,12 @@ class FriendDomain < ApplicationRecord destroy! end - def initialize_inbox_url! - self.inbox_url = default_inbox_url - end - - private - def default_inbox_url "https://#{domain}/inbox" end + private + def delete_for_friend! activity_id = ActivityPub::TagManager.instance.generate_uri_for(nil) payload = Oj.dump(delete_follow_activity(activity_id)) @@ -118,6 +114,9 @@ class FriendDomain < ApplicationRecord type: 'Follow', actor: ActivityPub::TagManager.instance.uri_for(some_local_account), object: ActivityPub::TagManager::COLLECTIONS[:public], + + # Cannot use inbox_url method because this model also has inbox_url column + inboxUrl: "https://#{Rails.configuration.x.web_domain}/inbox", } end diff --git a/spec/lib/activitypub/activity/follow_spec.rb b/spec/lib/activitypub/activity/follow_spec.rb index c27696ebaf..53ce9a29a6 100644 --- a/spec/lib/activitypub/activity/follow_spec.rb +++ b/spec/lib/activitypub/activity/follow_spec.rb @@ -310,6 +310,7 @@ RSpec.describe ActivityPub::Activity::Follow do let!(:friend) { Fabricate(:friend_domain, domain: 'abc.com', passive_state: :idle) } let!(:owner_user) { Fabricate(:user, role: UserRole.find_by(name: 'Owner')) } let!(:patch_user) { Fabricate(:user, role: Fabricate(:user_role, name: 'OhagiOps', permissions: UserRole::FLAGS[:manage_federation])) } + let(:inbox_url) { nil } let(:json) do { @@ -318,6 +319,7 @@ RSpec.describe ActivityPub::Activity::Follow do type: 'Follow', actor: ActivityPub::TagManager.instance.uri_for(sender), object: 'https://www.w3.org/ns/activitystreams#Public', + inboxUrl: inbox_url, }.with_indifferent_access end @@ -343,6 +345,24 @@ RSpec.describe ActivityPub::Activity::Follow do end end + context 'when no record and inbox_url is specified' do + let(:inbox_url) { 'https://ohagi.com/inbox' } + + before do + friend.update(domain: 'def.com') + end + + it 'marks the friend as pending' do + subject.perform + + friend = FriendDomain.find_by(domain: 'abc.com') + expect(friend).to_not be_nil + expect(friend.they_are_pending?).to be true + expect(friend.passive_follow_activity_id).to eq 'foo' + expect(friend.inbox_url).to eq 'https://ohagi.com/inbox' + end + end + context 'when my server is pending' do before do friend.update(active_state: :pending) diff --git a/spec/models/friend_domain_spec.rb b/spec/models/friend_domain_spec.rb index 647c39e5a8..65d090f9a7 100644 --- a/spec/models/friend_domain_spec.rb +++ b/spec/models/friend_domain_spec.rb @@ -21,6 +21,7 @@ describe FriendDomain do type: 'Follow', actor: 'https://cb6e6126.ngrok.io/actor', object: 'https://www.w3.org/ns/activitystreams#Public', + inboxUrl: 'https://cb6e6126.ngrok.io/inbox', }))).to have_been_made.once end end From 5746f4f1ee094998756b489346f12b7ba85f649c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?KMY=EF=BC=88=E9=9B=AA=E3=81=82=E3=81=99=E3=81=8B=EF=BC=89?= Date: Fri, 13 Oct 2023 19:13:44 +0900 Subject: [PATCH 5/9] =?UTF-8?q?Change:=20#100=20=E3=83=AA=E3=83=A2?= =?UTF-8?q?=E3=83=BC=E3=83=88=E3=81=AE=E3=82=B9=E3=82=BF=E3=83=B3=E3=83=97?= =?UTF-8?q?=E3=81=AB=E7=9B=B8=E4=B9=97=E3=82=8A=E3=81=97=E3=81=9F=E6=99=82?= =?UTF-8?q?=E3=80=81=E3=81=9D=E3=82=8C=E3=82=92=E3=83=95=E3=82=A9=E3=83=AD?= =?UTF-8?q?=E3=83=AF=E3=83=BC=E3=81=AE=E3=81=84=E3=82=8B=E3=82=B5=E3=83=BC?= =?UTF-8?q?=E3=83=90=E3=83=BC=E3=81=AB=E9=85=8D=E9=80=81=20(#111)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/emoji_reaction.rb | 4 ---- app/services/emoji_react_service.rb | 1 - 2 files changed, 5 deletions(-) diff --git a/app/models/emoji_reaction.rb b/app/models/emoji_reaction.rb index 5d6d58513c..a562865f3a 100644 --- a/app/models/emoji_reaction.rb +++ b/app/models/emoji_reaction.rb @@ -39,10 +39,6 @@ class EmojiReaction < ApplicationRecord custom_emoji.present? end - def remote_custom_emoji? - custom_emoji? && !custom_emoji.local? - end - def sign? status&.distributable_friend? end diff --git a/app/services/emoji_react_service.rb b/app/services/emoji_react_service.rb index 250868b3bc..c3135bdff2 100644 --- a/app/services/emoji_react_service.rb +++ b/app/services/emoji_react_service.rb @@ -62,7 +62,6 @@ class EmojiReactService < BaseService status = emoji_reaction.status return unless status.account.local? - return if emoji_reaction.remote_custom_emoji? ActivityPub::RawDistributionWorker.perform_async(build_json(emoji_reaction), status.account_id) end From 8405dd34f9044513474a96c97039efaaa72aa20e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?KMY=EF=BC=88=E9=9B=AA=E3=81=82=E3=81=99=E3=81=8B=EF=BC=89?= Date: Sat, 14 Oct 2023 07:56:46 +0900 Subject: [PATCH 6/9] =?UTF-8?q?Change:=20#52=20=E8=B3=BC=E8=AA=AD=E6=8B=92?= =?UTF-8?q?=E5=90=A6=E8=A8=AD=E5=AE=9A=E9=A0=85=E7=9B=AE=E3=82=92=E8=BF=BD?= =?UTF-8?q?=E5=8A=A0=E8=A8=AD=E5=AE=9A=E7=94=BB=E9=9D=A2=E3=81=AB=E7=A7=BB?= =?UTF-8?q?=E5=8B=95=20(#112)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/settings/privacy_controller.rb | 2 +- app/controllers/settings/privacy_extra_controller.rb | 2 +- app/views/settings/privacy/show.html.haml | 3 --- app/views/settings/privacy_extra/show.html.haml | 3 +++ 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/app/controllers/settings/privacy_controller.rb b/app/controllers/settings/privacy_controller.rb index e5c4e5a905..1102c89fad 100644 --- a/app/controllers/settings/privacy_controller.rb +++ b/app/controllers/settings/privacy_controller.rb @@ -18,7 +18,7 @@ class Settings::PrivacyController < Settings::BaseController private def account_params - params.require(:account).permit(:discoverable, :unlocked, :indexable, :show_collections, :dissubscribable, settings: UserSettings.keys) + params.require(:account).permit(:discoverable, :unlocked, :indexable, :show_collections, settings: UserSettings.keys) end def set_account diff --git a/app/controllers/settings/privacy_extra_controller.rb b/app/controllers/settings/privacy_extra_controller.rb index 54cedf2c4b..85364ec35d 100644 --- a/app/controllers/settings/privacy_extra_controller.rb +++ b/app/controllers/settings/privacy_extra_controller.rb @@ -18,7 +18,7 @@ class Settings::PrivacyExtraController < Settings::BaseController private def account_params - params.require(:account).permit(settings: UserSettings.keys) + params.require(:account).permit(:dissubscribable, settings: UserSettings.keys) end def set_account diff --git a/app/views/settings/privacy/show.html.haml b/app/views/settings/privacy/show.html.haml index 619429392e..9656ada005 100644 --- a/app/views/settings/privacy/show.html.haml +++ b/app/views/settings/privacy/show.html.haml @@ -24,9 +24,6 @@ .fields-group = ff.input :noai, wrapper: :with_label, kmyblue: true, label: I18n.t('simple_form.labels.defaults.setting_noai'), hint: I18n.t('simple_form.hints.defaults.setting_noai') - .fields-group - = f.input :dissubscribable, as: :boolean, wrapper: :with_label, kmyblue: true, hint: t('simple_form.hints.defaults.dissubscribable') - .fields-group = f.input :unlocked, as: :boolean, wrapper: :with_label diff --git a/app/views/settings/privacy_extra/show.html.haml b/app/views/settings/privacy_extra/show.html.haml index c688ad6373..5e102f6565 100644 --- a/app/views/settings/privacy_extra/show.html.haml +++ b/app/views/settings/privacy_extra/show.html.haml @@ -21,6 +21,9 @@ .fields-group = ff.input :link_preview, wrapper: :with_label, kmyblue: true, label: I18n.t('simple_form.labels.defaults.setting_link_preview'), hint: I18n.t('simple_form.hints.defaults.setting_link_preview') + .fields-group + = f.input :dissubscribable, as: :boolean, wrapper: :with_label, kmyblue: true, hint: t('simple_form.hints.defaults.dissubscribable') + .fields-group = ff.input :allow_quote, wrapper: :with_label, kmyblue: true, label: I18n.t('simple_form.labels.defaults.setting_allow_quote'), hint: false From 45e35309851e185b02f15ba881fee5126455d9cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?KMY=EF=BC=88=E9=9B=AA=E3=81=82=E3=81=99=E3=81=8B=EF=BC=89?= Date: Sun, 15 Oct 2023 11:36:34 +0900 Subject: [PATCH 7/9] Merge pull request from GHSA-jw42-6m49-65x8 --- app/services/emoji_react_service.rb | 3 + spec/services/emoji_react_service_spec.rb | 139 ++++++++++++++++++++++ 2 files changed, 142 insertions(+) create mode 100644 spec/services/emoji_react_service_spec.rb diff --git a/app/services/emoji_react_service.rb b/app/services/emoji_react_service.rb index c3135bdff2..a827ddc93e 100644 --- a/app/services/emoji_react_service.rb +++ b/app/services/emoji_react_service.rb @@ -23,7 +23,10 @@ class EmojiReactService < BaseService raise Mastodon::ValidationError, I18n.t('reactions.errors.duplication') unless emoji_reaction.nil? shortcode, domain = name.split('@') + domain = nil if TagManager.instance.local_domain?(domain) custom_emoji = CustomEmoji.find_by(shortcode: shortcode, domain: domain) + 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) status.touch # rubocop:disable Rails/SkipsModelValidations diff --git a/spec/services/emoji_react_service_spec.rb b/spec/services/emoji_react_service_spec.rb new file mode 100644 index 0000000000..62d81d57c5 --- /dev/null +++ b/spec/services/emoji_react_service_spec.rb @@ -0,0 +1,139 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe EmojiReactService, type: :service do + subject do + described_class.new.call(sender, status, name) + EmojiReaction.where(status: status, account: sender) + end + + let(:name) { '😀' } + let(:sender) { Fabricate(:user).account } + let(:author) { Fabricate(:user).account } + let(:status) { Fabricate(:status, account: author) } + + it 'with a simple case' do + expect(subject.count).to eq 1 + expect(subject.first.name).to eq '😀' + expect(subject.first.custom_emoji_id).to be_nil + end + + context 'with name duplication on same account' do + before { Fabricate(:emoji_reaction, status: status, name: '😀') } + + it 'react with emoji' do + expect(subject.count).to eq 1 + expect(subject.first.name).to eq '😀' + end + end + + context 'when multiple reactions by same account' do + let(:name) { '😂' } + + before { Fabricate(:emoji_reaction, account: sender, status: status, name: '😀') } + + it 'react with emoji' do + expect(subject.count).to eq 2 + expect(subject.pluck(:name)).to contain_exactly('😀', '😂') + end + end + + context 'when already reacted by other account' do + let(:name) { '😂' } + + before { Fabricate(:emoji_reaction, status: status, name: '😀') } + + it 'react with emoji' do + expect(subject.count).to eq 1 + expect(subject.pluck(:name)).to contain_exactly('😂') + end + end + + context 'when already reacted same emoji by other account', :tag do + before { Fabricate(:emoji_reaction, status: status, name: '😀') } + + it 'react with emoji' do + expect(subject.count).to eq 1 + expect(subject.first.name).to eq '😀' + end + end + + context 'when over limit' do + let(:name) { '🚗' } + + before do + Fabricate(:emoji_reaction, status: status, account: sender, name: '😀') + Fabricate(:emoji_reaction, status: status, account: sender, name: '😎') + Fabricate(:emoji_reaction, status: status, account: sender, name: '🐟') + end + + it 'react with emoji' do + expect { subject.count }.to raise_error Mastodon::ValidationError + + reactions = EmojiReaction.where(status: status, account: sender).pluck(:name) + expect(reactions.size).to eq 3 + expect(reactions).to contain_exactly('😀', '😎', '🐟') + end + end + + context 'with custom emoji of local' do + let(:name) { 'ohagi' } + let!(:custom_emoji) { Fabricate(:custom_emoji, shortcode: 'ohagi') } + + it 'react with emoji' do + expect(subject.count).to eq 1 + expect(subject.first.name).to eq 'ohagi' + expect(subject.first.custom_emoji.id).to eq custom_emoji.id + end + end + + context 'with custom emoji but not existing' do + let(:name) { 'ohagi' } + + it 'react with emoji' do + expect { subject.count }.to raise_error ActiveRecord::RecordInvalid + expect(EmojiReaction.exists?(status: status, account: sender, name: 'ohagi')).to be false + end + end + + context 'with custom emoji of remote' do + let(:name) { 'ohagi@foo.bar' } + let!(:custom_emoji) { Fabricate(:custom_emoji, shortcode: 'ohagi', domain: 'foo.bar') } + + before { Fabricate(:emoji_reaction, status: status, name: 'ohagi', custom_emoji: custom_emoji) } + + it 'react with emoji' do + expect(subject.count).to eq 1 + expect(subject.first.name).to eq 'ohagi' + expect(subject.first.custom_emoji.id).to eq custom_emoji.id + end + end + + context 'with custom emoji of remote without existing one' do + let(:name) { 'ohagi@foo.bar' } + + before { Fabricate(:custom_emoji, shortcode: 'ohagi', domain: 'foo.bar') } + + it 'react with emoji' do + expect(subject.count).to eq 0 + end + end + + context 'with custom emoji of remote but local has same name emoji' do + let(:name) { 'ohagi@foo.bar' } + let!(:custom_emoji) { Fabricate(:custom_emoji, shortcode: 'ohagi', domain: 'foo.bar') } + + before do + Fabricate(:custom_emoji, shortcode: 'ohagi', domain: nil) + Fabricate(:emoji_reaction, status: status, name: 'ohagi', custom_emoji: custom_emoji) + end + + it 'react with emoji' do + expect(subject.count).to eq 1 + expect(subject.first.name).to eq 'ohagi' + expect(subject.first.custom_emoji.id).to eq custom_emoji.id + expect(subject.first.custom_emoji.domain).to eq 'foo.bar' + end + end +end From 92301d59a46f9de6f5547b95b70944274c13e8b5 Mon Sep 17 00:00:00 2001 From: KMY Date: Sun, 15 Oct 2023 11:38:56 +0900 Subject: [PATCH 8/9] Bump version to 7.1 --- lib/mastodon/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/mastodon/version.rb b/lib/mastodon/version.rb index e1f1ed87dc..57f61bcacf 100644 --- a/lib/mastodon/version.rb +++ b/lib/mastodon/version.rb @@ -9,7 +9,7 @@ module Mastodon end def kmyblue_minor - 0 + 1 end def kmyblue_flag From e1e8476e1f2e4549054e919cf5a811dcf15d9421 Mon Sep 17 00:00:00 2001 From: KMY Date: Sun, 15 Oct 2023 12:19:46 +0900 Subject: [PATCH 9/9] =?UTF-8?q?Fix:=20=E3=82=B9=E3=82=BF=E3=83=B3=E3=83=97?= =?UTF-8?q?=E3=81=AE=E3=83=86=E3=82=B9=E3=83=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/emoji_reaction.rb | 6 +++++- spec/services/emoji_react_service_spec.rb | 6 +++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/app/models/emoji_reaction.rb b/app/models/emoji_reaction.rb index a562865f3a..e9dc6a37d3 100644 --- a/app/models/emoji_reaction.rb +++ b/app/models/emoji_reaction.rb @@ -40,7 +40,11 @@ class EmojiReaction < ApplicationRecord end def sign? - status&.distributable_friend? + true + end + + def object_type + :emoji_reaction end private diff --git a/spec/services/emoji_react_service_spec.rb b/spec/services/emoji_react_service_spec.rb index 62d81d57c5..629a7818d4 100644 --- a/spec/services/emoji_react_service_spec.rb +++ b/spec/services/emoji_react_service_spec.rb @@ -99,7 +99,7 @@ RSpec.describe EmojiReactService, type: :service do context 'with custom emoji of remote' do let(:name) { 'ohagi@foo.bar' } - let!(:custom_emoji) { Fabricate(:custom_emoji, shortcode: 'ohagi', domain: 'foo.bar') } + let!(:custom_emoji) { Fabricate(:custom_emoji, shortcode: 'ohagi', domain: 'foo.bar', uri: 'https://foo.bar/emoji/ohagi') } before { Fabricate(:emoji_reaction, status: status, name: 'ohagi', custom_emoji: custom_emoji) } @@ -113,7 +113,7 @@ RSpec.describe EmojiReactService, type: :service do context 'with custom emoji of remote without existing one' do let(:name) { 'ohagi@foo.bar' } - before { Fabricate(:custom_emoji, shortcode: 'ohagi', domain: 'foo.bar') } + before { Fabricate(:custom_emoji, shortcode: 'ohagi', domain: 'foo.bar', uri: 'https://foo.bar/emoji/ohagi') } it 'react with emoji' do expect(subject.count).to eq 0 @@ -122,7 +122,7 @@ RSpec.describe EmojiReactService, type: :service do context 'with custom emoji of remote but local has same name emoji' do let(:name) { 'ohagi@foo.bar' } - let!(:custom_emoji) { Fabricate(:custom_emoji, shortcode: 'ohagi', domain: 'foo.bar') } + let!(:custom_emoji) { Fabricate(:custom_emoji, shortcode: 'ohagi', domain: 'foo.bar', uri: 'https://foo.bar/emoji/ohagi') } before do Fabricate(:custom_emoji, shortcode: 'ohagi', domain: nil)