From 9b6a336a198cfbebd56b49b28a3d35188c4d9c2d 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, 7 Oct 2023 11:57:38 +0900 Subject: [PATCH 1/9] =?UTF-8?q?=E4=BB=96=E3=82=B5=E3=83=BC=E3=83=90?= =?UTF-8?q?=E3=83=BC=E3=81=8B=E3=82=89=E3=82=AB=E3=82=B9=E3=82=BF=E3=83=A0?= =?UTF-8?q?=E7=B5=B5=E6=96=87=E5=AD=97=E3=81=AB=E3=82=88=E3=82=8B=E3=82=B9?= =?UTF-8?q?=E3=82=BF=E3=83=B3=E3=83=97=E3=82=92=E5=8F=97=E3=81=91=E5=8F=96?= =?UTF-8?q?=E3=81=A3=E3=81=9F=E6=99=82=E3=81=AB=E3=80=81=E3=83=A9=E3=82=A4?= =?UTF-8?q?=E3=82=BB=E3=83=B3=E3=82=B9=E6=83=85=E5=A0=B1=E3=82=92=E4=BF=9D?= =?UTF-8?q?=E5=AD=98=E3=81=99=E3=82=8B=EF=BC=8B=E3=81=A4=E3=81=84=E3=81=A7?= =?UTF-8?q?=E3=81=AB=E3=83=86=E3=82=B9=E3=83=88=20(#65)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Wip: スタンプを他サーバーから受信するテスト作成、カスタム絵文字にdomainプロパティを追加 * Wip: ドメインに関するイレギュラーな状況に対応 * Wip: 他のサーバーのカスタム絵文字を送信するときのID変更処理を追加 * Wip: カスタム絵文字のIDを判定する場所を変更 * Wip: カスタム絵文字のURIを返す処理を削除(不要) * Wip: 絵文字リアクション受け入れ処理リファクタリング * Wip: 外部へ送信するカスタム絵文字データにライセンス情報を追加、ライセンス情報の受信をテストに追加 * Wip: ドメインブロックのテストを追加 * Wip: ついでに通常のドメインブロックを追加 --- app/lib/activitypub/activity/like.rb | 58 +++-- .../activitypub/parser/custom_emoji_parser.rb | 2 +- .../activitypub/emoji_serializer.rb | 8 +- spec/lib/activitypub/activity/like_spec.rb | 221 +++++++++++++++++- 4 files changed, 273 insertions(+), 16 deletions(-) diff --git a/app/lib/activitypub/activity/like.rb b/app/lib/activitypub/activity/like.rb index ebfac9a868..5e34cc9dc5 100644 --- a/app/lib/activitypub/activity/like.rb +++ b/app/lib/activitypub/activity/like.rb @@ -7,7 +7,7 @@ class ActivityPub::Activity::Like < ActivityPub::Activity def perform @original_status = status_from_uri(object_uri) - return if @original_status.nil? || delete_arrived_first?(@json['id']) || reject_favourite? + return if @original_status.nil? || delete_arrived_first?(@json['id']) || block_domain? || reject_favourite? if shortcode.nil? || !Setting.enable_emoji_reaction process_favourite @@ -34,19 +34,11 @@ class ActivityPub::Activity::Like < ActivityPub::Activity def process_emoji_reaction return if !@original_status.account.local? && !Setting.receive_other_servers_emoji_reaction + # custom emoji + emoji = nil if emoji_tag.present? - return if emoji_tag['id'].blank? || emoji_tag['name'].blank? || emoji_tag['icon'].blank? || emoji_tag['icon']['url'].blank? - - image_url = emoji_tag['icon']['url'] - uri = emoji_tag['id'] - domain = URI.split(uri)[2] - - emoji = CustomEmoji.find_or_create_by!(shortcode: shortcode, domain: domain) do |emoji_data| - emoji_data.uri = uri - emoji_data.image_remote_url = image_url - end - - Trends.statuses.register(@original_status) + emoji = process_emoji(emoji_tag) + return if emoji.nil? end reaction = nil @@ -58,6 +50,7 @@ class ActivityPub::Activity::Like < ActivityPub::Activity reaction = @original_status.emoji_reactions.create!(account: @account, name: shortcode, custom_emoji: emoji, uri: @json['id']) end + Trends.statuses.register(@original_status) write_stream(reaction) if @original_status.account.local? @@ -95,6 +88,45 @@ class ActivityPub::Activity::Like < ActivityPub::Activity end end + def process_emoji(tag) + custom_emoji_parser = ActivityPub::Parser::CustomEmojiParser.new(tag) + + return if custom_emoji_parser.shortcode.blank? || custom_emoji_parser.image_remote_url.blank? + + emoji = CustomEmoji.find_by(shortcode: custom_emoji_parser.shortcode, domain: @account.domain) + + return unless emoji.nil? || custom_emoji_parser.image_remote_url != emoji.image_remote_url || (custom_emoji_parser.updated_at && custom_emoji_parser.updated_at >= emoji.updated_at) + + domain = emoji_tag['domain'] || URI.split(custom_emoji_parser.uri)[2] || @account.domain + domain = nil if domain == Rails.configuration.x.local_domain || domain == Rails.configuration.x.web_domain + + return if domain.present? && skip_download?(domain) + + begin + emoji ||= CustomEmoji.new( + domain: domain, + shortcode: custom_emoji_parser.shortcode, + uri: custom_emoji_parser.uri, + is_sensitive: custom_emoji_parser.is_sensitive, + license: custom_emoji_parser.license + ) + emoji.image_remote_url = custom_emoji_parser.image_remote_url + emoji.save + rescue Seahorse::Client::NetworkingError => e + Rails.logger.warn "Error storing emoji: #{e}" + end + + emoji + end + + def skip_download?(domain) + DomainBlock.reject_media?(domain) + end + + def block_domain? + DomainBlock.blocked?(@account.domain) + end + def misskey_favourite? misskey_shortcode = @json['_misskey_reaction']&.delete(':') diff --git a/app/lib/activitypub/parser/custom_emoji_parser.rb b/app/lib/activitypub/parser/custom_emoji_parser.rb index 481199c72d..e217b5ec96 100644 --- a/app/lib/activitypub/parser/custom_emoji_parser.rb +++ b/app/lib/activitypub/parser/custom_emoji_parser.rb @@ -30,6 +30,6 @@ class ActivityPub::Parser::CustomEmojiParser end def license - @json['license'] + @json['license'] || @json['licence'] end end diff --git a/app/serializers/activitypub/emoji_serializer.rb b/app/serializers/activitypub/emoji_serializer.rb index 4dc38f3ea6..98525d3131 100644 --- a/app/serializers/activitypub/emoji_serializer.rb +++ b/app/serializers/activitypub/emoji_serializer.rb @@ -5,7 +5,9 @@ class ActivityPub::EmojiSerializer < ActivityPub::Serializer context_extensions :emoji - attributes :id, :type, :name, :updated + attributes :id, :type, :domain, :name, :is_sensitive, :updated + + attribute :license, if: -> { object.license.present? } has_one :icon, serializer: ActivityPub::ImageSerializer @@ -17,6 +19,10 @@ class ActivityPub::EmojiSerializer < ActivityPub::Serializer 'Emoji' end + def domain + object.domain.presence || Rails.configuration.x.local_domain + end + def icon object.image end diff --git a/spec/lib/activitypub/activity/like_spec.rb b/spec/lib/activitypub/activity/like_spec.rb index 51493f7bc8..bdeda34f12 100644 --- a/spec/lib/activitypub/activity/like_spec.rb +++ b/spec/lib/activitypub/activity/like_spec.rb @@ -29,6 +29,225 @@ RSpec.describe ActivityPub::Activity::Like do end end + describe '#perform when receive emoji reaction' do + subject do + described_class.new(json, sender).perform + EmojiReaction.where(status: status) + end + + before do + stub_request(:get, 'http://example.com/emoji.png').to_return(body: attachment_fixture('emojo.png')) + end + + let(:json) do + { + '@context': 'https://www.w3.org/ns/activitystreams', + id: 'foo', + type: 'Like', + actor: ActivityPub::TagManager.instance.uri_for(sender), + object: ActivityPub::TagManager.instance.uri_for(status), + content: content, + tag: tag, + }.with_indifferent_access + end + let(:content) { nil } + let(:tag) { nil } + + context 'with unicode emoji' do + let(:content) { '😀' } + + it 'create emoji reaction' do + expect(subject.count).to eq 1 + expect(subject.first.name).to eq '😀' + expect(subject.first.account).to eq sender + expect(sender.favourited?(status)).to be false + end + end + + context 'with custom emoji' do + let(:content) { ':tinking:' } + let(:tag) do + { + id: 'https://example.com/aaa', + type: 'Emoji', + icon: { + url: 'http://example.com/emoji.png', + }, + name: 'tinking', + license: 'Everyone but Ohagi', + } + end + + it 'create emoji reaction' do + expect(subject.count).to eq 1 + expect(subject.first.name).to eq 'tinking' + expect(subject.first.account).to eq sender + expect(subject.first.custom_emoji).to_not be_nil + expect(subject.first.custom_emoji.shortcode).to eq 'tinking' + expect(subject.first.custom_emoji.domain).to eq 'example.com' + expect(sender.favourited?(status)).to be false + end + + it 'custom emoji license is saved' do + expect(subject.first.custom_emoji.license).to eq 'Everyone but Ohagi' + end + end + + context 'with custom emoji and custom domain' do + let(:content) { ':tinking:' } + let(:tag) do + { + id: 'https://example.com/aaa', + type: 'Emoji', + domain: 'post.kmycode.net', + icon: { + url: 'http://example.com/emoji.png', + }, + name: 'tinking', + } + end + + it 'create emoji reaction' do + expect(subject.count).to eq 1 + expect(subject.first.name).to eq 'tinking' + expect(subject.first.account).to eq sender + expect(subject.first.custom_emoji).to_not be_nil + expect(subject.first.custom_emoji.shortcode).to eq 'tinking' + expect(subject.first.custom_emoji.domain).to eq 'post.kmycode.net' + expect(sender.favourited?(status)).to be false + end + end + + context 'with custom emoji but invalid id' do + let(:content) { ':tinking:' } + let(:tag) do + { + id: 'aaa', + type: 'Emoji', + icon: { + url: 'http://example.com/emoji.png', + }, + name: 'tinking', + } + end + + it 'create emoji reaction' do + expect(subject.count).to eq 1 + expect(subject.first.name).to eq 'tinking' + expect(subject.first.account).to eq sender + expect(subject.first.custom_emoji).to_not be_nil + expect(subject.first.custom_emoji.shortcode).to eq 'tinking' + expect(subject.first.custom_emoji.domain).to eq 'example.com' + expect(sender.favourited?(status)).to be false + end + end + + context 'with custom emoji but local domain' do + let(:content) { ':tinking:' } + let(:tag) do + { + id: 'aaa', + type: 'Emoji', + domain: Rails.configuration.x.local_domain, + icon: { + url: 'http://example.com/emoji.png', + }, + name: 'tinking', + } + end + + it 'create emoji reaction' do + expect(subject.count).to eq 1 + expect(subject.first.name).to eq 'tinking' + expect(subject.first.account).to eq sender + expect(subject.first.custom_emoji).to_not be_nil + expect(subject.first.custom_emoji.shortcode).to eq 'tinking' + expect(subject.first.custom_emoji.domain).to be_nil + expect(sender.favourited?(status)).to be false + end + end + + context 'with unicode emoji and reject_media enabled' do + let(:content) { '😀' } + + before do + Fabricate(:domain_block, domain: 'example.com', severity: :noop, reject_media: true) + end + + it 'create emoji reaction' do + expect(subject.count).to eq 1 + expect(subject.first.name).to eq '😀' + expect(subject.first.account).to eq sender + expect(sender.favourited?(status)).to be false + end + end + + context 'with custom emoji and reject_media enabled' do + let(:content) { ':tinking:' } + let(:tag) do + { + id: 'https://example.com/aaa', + type: 'Emoji', + icon: { + url: 'http://example.com/emoji.png', + }, + name: 'tinking', + } + end + + before do + Fabricate(:domain_block, domain: 'example.com', severity: :noop, reject_media: true) + end + + it 'create emoji reaction' do + expect(subject.count).to eq 0 + expect(sender.favourited?(status)).to be false + end + end + + context 'when emoji reaction is disabled' do + let(:content) { '😀' } + + before do + Form::AdminSettings.new(enable_emoji_reaction: false).save + end + + it 'create emoji reaction' do + expect(subject.count).to eq 0 + expect(sender.favourited?(status)).to be true + end + end + + context 'when emoji reaction between other servers is disabled' do + let(:recipient) { Fabricate(:account, domain: 'narrow.com', uri: 'https://narrow.com/') } + let(:content) { '😀' } + + before do + Form::AdminSettings.new(receive_other_servers_emoji_reaction: false).save + end + + it 'create emoji reaction' do + expect(subject.count).to eq 0 + expect(sender.favourited?(status)).to be false + end + end + + context 'when emoji reaction between other servers is disabled but that status is local' do + let(:content) { '😀' } + + before do + Form::AdminSettings.new(receive_other_servers_emoji_reaction: false).save + end + + it 'create emoji reaction' do + expect(subject.count).to eq 1 + expect(subject.first.name).to eq '😀' + expect(subject.first.account).to eq sender + expect(sender.favourited?(status)).to be false + end + end + end + describe '#perform when domain_block' do subject { described_class.new(json, sender) } @@ -50,7 +269,7 @@ RSpec.describe ActivityPub::Activity::Like do subject.perform end - it 'does not create a favourite from sender to status', pending: 'considering spec' do + it 'does not create a favourite from sender to status' do expect(sender.favourited?(status)).to be false end end From 7c09b83b7aebc8258a071f9d9effb65df409da4d Mon Sep 17 00:00:00 2001 From: KMY Date: Sat, 7 Oct 2023 12:13:18 +0900 Subject: [PATCH 2/9] =?UTF-8?q?Fix:=20=E3=81=99=E3=81=A7=E3=81=AB=E5=90=8C?= =?UTF-8?q?=E3=81=98=E3=82=AB=E3=82=B9=E3=82=BF=E3=83=A0=E7=B5=B5=E6=96=87?= =?UTF-8?q?=E5=AD=97=E3=81=8C=E5=AD=98=E5=9C=A8=E3=81=99=E3=82=8B=E5=A0=B4?= =?UTF-8?q?=E5=90=88=E3=80=81=E3=82=B9=E3=82=BF=E3=83=B3=E3=83=97=E3=82=92?= =?UTF-8?q?=E5=8F=97=E3=81=91=E5=85=A5=E3=82=8C=E3=81=AA=E3=81=84=E5=95=8F?= =?UTF-8?q?=E9=A1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/lib/activitypub/activity/like.rb | 14 ++++++----- spec/lib/activitypub/activity/like_spec.rb | 29 ++++++++++++++++++++++ 2 files changed, 37 insertions(+), 6 deletions(-) diff --git a/app/lib/activitypub/activity/like.rb b/app/lib/activitypub/activity/like.rb index 5e34cc9dc5..298a81b292 100644 --- a/app/lib/activitypub/activity/like.rb +++ b/app/lib/activitypub/activity/like.rb @@ -93,15 +93,17 @@ class ActivityPub::Activity::Like < ActivityPub::Activity return if custom_emoji_parser.shortcode.blank? || custom_emoji_parser.image_remote_url.blank? - emoji = CustomEmoji.find_by(shortcode: custom_emoji_parser.shortcode, domain: @account.domain) - - return unless emoji.nil? || custom_emoji_parser.image_remote_url != emoji.image_remote_url || (custom_emoji_parser.updated_at && custom_emoji_parser.updated_at >= emoji.updated_at) - - domain = emoji_tag['domain'] || URI.split(custom_emoji_parser.uri)[2] || @account.domain + domain = tag['domain'] || URI.split(custom_emoji_parser.uri)[2] || @account.domain domain = nil if domain == Rails.configuration.x.local_domain || domain == Rails.configuration.x.web_domain - return if domain.present? && skip_download?(domain) + emoji = CustomEmoji.find_by(shortcode: custom_emoji_parser.shortcode, domain: domain) + + return emoji unless emoji.nil? || + custom_emoji_parser.image_remote_url != emoji.image_remote_url || + (custom_emoji_parser.updated_at && custom_emoji_parser.updated_at >= emoji.updated_at) || + custom_emoji_parser.license != emoji.license + begin emoji ||= CustomEmoji.new( domain: domain, diff --git a/spec/lib/activitypub/activity/like_spec.rb b/spec/lib/activitypub/activity/like_spec.rb index bdeda34f12..9991ba37dc 100644 --- a/spec/lib/activitypub/activity/like_spec.rb +++ b/spec/lib/activitypub/activity/like_spec.rb @@ -93,6 +93,35 @@ RSpec.describe ActivityPub::Activity::Like do end end + context 'with custom emoji but that is existing on local server' do + let(:content) { ':tinking:' } + let(:tag) do + { + id: 'https://example.com/aaa', + type: 'Emoji', + icon: { + url: 'http://example.com/emoji.png', + }, + name: 'tinking', + license: 'Everyone but Ohagi', + } + end + + before do + Fabricate(:custom_emoji, domain: 'example.com', uri: 'https://example.com/aaa', image_remote_url: 'http://example.com/emoji.png', shortcode: 'tinking', license: 'Everyone but Ohagi') + end + + it 'create emoji reaction' do + expect(subject.count).to eq 1 + expect(subject.first.name).to eq 'tinking' + expect(subject.first.account).to eq sender + expect(subject.first.custom_emoji).to_not be_nil + expect(subject.first.custom_emoji.shortcode).to eq 'tinking' + expect(subject.first.custom_emoji.domain).to eq 'example.com' + expect(sender.favourited?(status)).to be false + end + end + context 'with custom emoji and custom domain' do let(:content) { ':tinking:' } let(:tag) do From 76e4ad05ae930676e5c1ac637bb275ce19e392f8 Mon Sep 17 00:00:00 2001 From: KMY Date: Sat, 7 Oct 2023 14:09:02 +0900 Subject: [PATCH 3/9] =?UTF-8?q?Fix:=20Account=E3=81=AE=E3=83=86=E3=82=B9?= =?UTF-8?q?=E3=83=88=E3=81=8C=E3=81=9F=E3=81=BE=E3=81=AB=E8=90=BD=E3=81=A1?= =?UTF-8?q?=E3=82=8B=E5=95=8F=E9=A1=8C=EF=BC=88Mastodon=E6=9C=AC=E5=AE=B6?= =?UTF-8?q?=E3=81=AE=E5=95=8F=E9=A1=8C=EF=BC=9F=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- spec/models/account_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/models/account_spec.rb b/spec/models/account_spec.rb index fc30b09167..dd1f63ce75 100644 --- a/spec/models/account_spec.rb +++ b/spec/models/account_spec.rb @@ -854,7 +854,7 @@ RSpec.describe Account do match = Fabricate(:account, username: 'pattern_and_suffix') account = Fabricate(:account, username: 'prefix_and_pattern') - expect(described_class.matches_username('pattern')).to eq [match, account] + expect(described_class.matches_username('pattern')).to contain_exactly(match, account) end end From 4a6b0062b28405606b10057506fc8b8e211d51b8 Mon Sep 17 00:00:00 2001 From: KMY Date: Sat, 7 Oct 2023 14:10:19 +0900 Subject: [PATCH 4/9] =?UTF-8?q?=E3=82=AB=E3=82=B9=E3=82=BF=E3=83=A0?= =?UTF-8?q?=E7=B5=B5=E6=96=87=E5=AD=97=E3=81=AE=E3=83=A9=E3=82=A4=E3=82=BB?= =?UTF-8?q?=E3=83=B3=E3=82=B9=E5=A4=89=E6=9B=B4=E3=82=92=E4=BB=96=E3=81=AE?= =?UTF-8?q?=E5=A0=B4=E6=89=80=E3=81=A7=E3=82=82=E4=BF=9D=E5=AD=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/lib/activitypub/activity/create.rb | 11 +++++++---- app/lib/activitypub/activity/like.rb | 6 +++--- .../activitypub/process_status_update_service.rb | 9 +++++++-- 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/app/lib/activitypub/activity/create.rb b/app/lib/activitypub/activity/create.rb index 6b8a715330..2726df5c3b 100644 --- a/app/lib/activitypub/activity/create.rb +++ b/app/lib/activitypub/activity/create.rb @@ -262,17 +262,20 @@ class ActivityPub::Activity::Create < ActivityPub::Activity emoji = CustomEmoji.find_by(shortcode: custom_emoji_parser.shortcode, domain: @account.domain) - return unless emoji.nil? || custom_emoji_parser.image_remote_url != emoji.image_remote_url || (custom_emoji_parser.updated_at && custom_emoji_parser.updated_at >= emoji.updated_at) + return unless emoji.nil? || + custom_emoji_parser.image_remote_url != emoji.image_remote_url || + (custom_emoji_parser.updated_at && custom_emoji_parser.updated_at >= emoji.updated_at) || + custom_emoji_parser.license != emoji.license begin emoji ||= CustomEmoji.new( domain: @account.domain, shortcode: custom_emoji_parser.shortcode, - uri: custom_emoji_parser.uri, - is_sensitive: custom_emoji_parser.is_sensitive, - license: custom_emoji_parser.license + uri: custom_emoji_parser.uri ) emoji.image_remote_url = custom_emoji_parser.image_remote_url + emoji.license = custom_emoji_parser.license + emoji.is_sensitive = custom_emoji_parser.is_sensitive emoji.save rescue Seahorse::Client::NetworkingError => e Rails.logger.warn "Error storing emoji: #{e}" diff --git a/app/lib/activitypub/activity/like.rb b/app/lib/activitypub/activity/like.rb index 298a81b292..9d2abcccf5 100644 --- a/app/lib/activitypub/activity/like.rb +++ b/app/lib/activitypub/activity/like.rb @@ -108,11 +108,11 @@ class ActivityPub::Activity::Like < ActivityPub::Activity emoji ||= CustomEmoji.new( domain: domain, shortcode: custom_emoji_parser.shortcode, - uri: custom_emoji_parser.uri, - is_sensitive: custom_emoji_parser.is_sensitive, - license: custom_emoji_parser.license + uri: custom_emoji_parser.uri ) emoji.image_remote_url = custom_emoji_parser.image_remote_url + emoji.license = custom_emoji_parser.license + emoji.is_sensitive = custom_emoji_parser.is_sensitive emoji.save rescue Seahorse::Client::NetworkingError => e Rails.logger.warn "Error storing emoji: #{e}" diff --git a/app/services/activitypub/process_status_update_service.rb b/app/services/activitypub/process_status_update_service.rb index dd6c8bc8a1..92d5788151 100644 --- a/app/services/activitypub/process_status_update_service.rb +++ b/app/services/activitypub/process_status_update_service.rb @@ -239,11 +239,16 @@ class ActivityPub::ProcessStatusUpdateService < BaseService emoji = CustomEmoji.find_by(shortcode: custom_emoji_parser.shortcode, domain: @account.domain) - next unless emoji.nil? || custom_emoji_parser.image_remote_url != emoji.image_remote_url || (custom_emoji_parser.updated_at && custom_emoji_parser.updated_at >= emoji.updated_at) + next unless emoji.nil? || + custom_emoji_parser.image_remote_url != emoji.image_remote_url || + (custom_emoji_parser.updated_at && custom_emoji_parser.updated_at >= emoji.updated_at) || + custom_emoji_parser.license != emoji.license begin - emoji ||= CustomEmoji.new(domain: @account.domain, shortcode: custom_emoji_parser.shortcode, uri: custom_emoji_parser.uri, is_sensitive: custom_emoji_parser.is_sensitive, license: custom_emoji_parser.license) + emoji ||= CustomEmoji.new(domain: @account.domain, shortcode: custom_emoji_parser.shortcode, uri: custom_emoji_parser.uri) emoji.image_remote_url = custom_emoji_parser.image_remote_url + emoji.license = custom_emoji_parser.license + emoji.is_sensitive = custom_emoji_parser.is_sensitive emoji.save rescue Seahorse::Client::NetworkingError => e Rails.logger.warn "Error storing emoji: #{e}" From 30edfda9e40814183711df3fd0228eaf92f915e9 Mon Sep 17 00:00:00 2001 From: KMY Date: Sat, 7 Oct 2023 15:31:35 +0900 Subject: [PATCH 5/9] =?UTF-8?q?=E4=BB=96=E3=81=AE=E3=83=86=E3=82=B9?= =?UTF-8?q?=E3=83=88=E3=82=82=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- spec/models/account_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/models/account_spec.rb b/spec/models/account_spec.rb index dd1f63ce75..c13d57c761 100644 --- a/spec/models/account_spec.rb +++ b/spec/models/account_spec.rb @@ -845,7 +845,7 @@ RSpec.describe Account do match = Fabricate(:account, display_name: 'pattern and suffix') account = Fabricate(:account, display_name: 'prefix and pattern') - expect(described_class.matches_display_name('pattern')).to eq [match, account] + expect(described_class.matches_display_name('pattern')).to contain_exactly(match, account) end end From f6b583aca733c5670c30d9171402631e58b94099 Mon Sep 17 00:00:00 2001 From: KMY Date: Sat, 7 Oct 2023 21:45:46 +0900 Subject: [PATCH 6/9] =?UTF-8?q?#66=20=E6=A4=9C=E7=B4=A2=E9=80=9F=E5=BA=A6?= =?UTF-8?q?=E6=94=B9=E5=96=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...7090808_improve_search_for_account_statuses.rb | 15 +++++++++++++++ db/schema.rb | 3 ++- 2 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 db/migrate/20231007090808_improve_search_for_account_statuses.rb diff --git a/db/migrate/20231007090808_improve_search_for_account_statuses.rb b/db/migrate/20231007090808_improve_search_for_account_statuses.rb new file mode 100644 index 0000000000..e1817ed95c --- /dev/null +++ b/db/migrate/20231007090808_improve_search_for_account_statuses.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +require Rails.root.join('lib', 'mastodon', 'migration_helpers') + +class ImproveSearchForAccountStatuses < ActiveRecord::Migration[7.0] + include Mastodon::MigrationHelpers + + disable_ddl_transaction! + + def change + safety_assured do + add_index :statuses, [:account_id, :reblog_of_id, :deleted_at, :searchability], name: 'index_statuses_for_get_following_accounts_to_search', where: 'deleted_at IS NULL AND reblog_of_id IS NULL AND searchability IN (0, 10, 1)' + end + end +end diff --git a/db/schema.rb b/db/schema.rb index c5dcfc6a33..24dc5450e1 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.0].define(version: 2023_09_19_232836) do +ActiveRecord::Schema[7.0].define(version: 2023_10_07_090808) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -1190,6 +1190,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_09_19_232836) do t.boolean "markdown", default: false t.integer "limited_scope" t.index ["account_id", "id", "visibility", "updated_at"], name: "index_statuses_20190820", order: { id: :desc }, where: "(deleted_at IS NULL)" + t.index ["account_id", "reblog_of_id", "deleted_at", "searchability"], name: "index_statuses_for_get_following_accounts_to_search", where: "((deleted_at IS NULL) AND (reblog_of_id IS NULL) AND (searchability = ANY (ARRAY[0, 10, 1])))" t.index ["account_id"], name: "index_statuses_on_account_id" t.index ["deleted_at"], name: "index_statuses_on_deleted_at", where: "(deleted_at IS NOT NULL)" t.index ["id", "account_id"], name: "index_statuses_local_20190824", order: { id: :desc }, where: "((local OR (uri IS NULL)) AND (deleted_at IS NULL) AND (visibility = 0) AND (reblog_of_id IS NULL) AND ((NOT reply) OR (in_reply_to_account_id = account_id)))" From f347df4e4c805342e97998862cebf3d26d5eb703 Mon Sep 17 00:00:00 2001 From: KMY Date: Sun, 8 Oct 2023 18:39:20 +0900 Subject: [PATCH 7/9] =?UTF-8?q?Fix:=20=E5=8F=82=E7=85=A7=E3=81=A7=E9=9D=9E?= =?UTF-8?q?=E5=85=AC=E9=96=8B=E6=8A=95=E7=A8=BF=E3=81=8C=E8=A6=8B=E3=81=88?= =?UTF-8?q?=E3=81=A6=E3=81=97=E3=81=BE=E3=81=86=E5=95=8F=E9=A1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/api/v1/statuses_controller.rb | 2 +- app/models/concerns/status_threading_concern.rb | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/app/controllers/api/v1/statuses_controller.rb b/app/controllers/api/v1/statuses_controller.rb index 1df399405a..065ec07613 100644 --- a/app/controllers/api/v1/statuses_controller.rb +++ b/app/controllers/api/v1/statuses_controller.rb @@ -44,7 +44,7 @@ class Api::V1::StatusesController < Api::BaseController ancestors_results = @status.in_reply_to_id.nil? ? [] : @status.ancestors(ancestors_limit, current_account) descendants_results = @status.descendants(descendants_limit, current_account, descendants_depth_limit) - references_results = @status.references + references_results = @status.readable_references(current_account) loaded_ancestors = cache_collection(ancestors_results, Status) loaded_descendants = cache_collection(descendants_results, Status) loaded_references = cache_collection(references_results, Status) diff --git a/app/models/concerns/status_threading_concern.rb b/app/models/concerns/status_threading_concern.rb index 38d0f393b7..52b397b47d 100644 --- a/app/models/concerns/status_threading_concern.rb +++ b/app/models/concerns/status_threading_concern.rb @@ -11,6 +11,15 @@ module StatusThreadingConcern find_statuses_from_tree_path(descendant_ids(limit, depth), account, promote: true) end + def readable_references(account = nil) + statuses = references.to_a + account_ids = statuses.map(&:account_id).uniq + domains = statuses.filter_map(&:account_domain).uniq + relations = account&.relations_map(account_ids, domains) || {} + statuses.reject! { |status| StatusFilter.new(status, account, relations).filtered? } + statuses + end + def self_replies(limit) account.statuses.where(in_reply_to_id: id, visibility: [:public, :unlisted, :public_unlisted, :login]).reorder(id: :asc).limit(limit) end From b8d2a306463cfe8b312aa1f8173917fe1ef78b65 Mon Sep 17 00:00:00 2001 From: KMY Date: Sun, 8 Oct 2023 18:44:35 +0900 Subject: [PATCH 8/9] Bump version to 5.3 LTS --- 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 611f439135..c5cc6d8ce7 100644 --- a/lib/mastodon/version.rb +++ b/lib/mastodon/version.rb @@ -9,7 +9,7 @@ module Mastodon end def kmyblue_minor - 2 + 3 end def kmyblue_flag From 3a1b03e2b4af123fa4a0f1bb70b3edae66969b42 Mon Sep 17 00:00:00 2001 From: KMY Date: Sun, 8 Oct 2023 20:18:33 +0900 Subject: [PATCH 9/9] Bump version to 5.4 LTS --- lib/mastodon/version.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/mastodon/version.rb b/lib/mastodon/version.rb index d12507eb08..3e443ad6c2 100644 --- a/lib/mastodon/version.rb +++ b/lib/mastodon/version.rb @@ -9,7 +9,7 @@ module Mastodon end def kmyblue_minor - 3 + 4 end def kmyblue_flag @@ -29,7 +29,7 @@ module Mastodon end def default_prerelease - 'rc1' + '' end def prerelease