自分のフォロワー限定投稿に対するリプライがホームタイムラインで見えないことが有る問題を修正 (#13835)

* fix: reply to my follower notes are not shown on the home timeline

* fix: reply to follower note by non-following is on social timeline

* docs: changelog

* test: add endpoint test for changes

* test(e2e): 自分のfollowers投稿に対するリプライが流れる

* test(e2e/streaming): 自分のfollowers投稿に対するリプライが流れる

* test(e2e/streaming): フォローしていないユーザによるフォロワー限定投稿に対するリプライがソーシャルタイムラインで表示されることがある問題

* test(e2e/timelines): try fixing typecheck error

---------

Co-authored-by: Sayamame-beans <61457993+Sayamame-beans@users.noreply.github.com>
This commit is contained in:
anatawa12
2024-07-30 19:44:08 +09:00
committed by GitHub
parent 86b4f49880
commit 8f40f932e4
7 changed files with 165 additions and 5 deletions

View File

@@ -143,6 +143,12 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
];
}
const [
followings,
] = await Promise.all([
this.cacheService.userFollowingsCache.fetch(me.id),
]);
const redisTimeline = await this.fanoutTimelineEndpointService.timeline({
untilId,
sinceId,
@@ -153,6 +159,13 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
useDbFallback: serverSettings.enableFanoutTimelineDbFallback,
alwaysIncludeMyNotes: true,
excludePureRenotes: !ps.withRenotes,
noteFilter: note => {
if (note.reply && note.reply.visibility === 'followers') {
if (!Object.hasOwn(followings, note.reply.userId) && note.reply.userId !== me.id) return false;
}
return true;
},
dbFallback: async (untilId, sinceId, limit) => await this.getFromDb({
untilId,
sinceId,

View File

@@ -114,7 +114,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
excludePureRenotes: !ps.withRenotes,
noteFilter: note => {
if (note.reply && note.reply.visibility === 'followers') {
if (!Object.hasOwn(followings, note.reply.userId)) return false;
if (!Object.hasOwn(followings, note.reply.userId) && note.reply.userId !== me.id) return false;
}
return true;

View File

@@ -60,7 +60,7 @@ class HomeTimelineChannel extends Channel {
const reply = note.reply;
if (this.following[note.userId]?.withReplies) {
// 自分のフォローしていないユーザーの visibility: followers な投稿への返信は弾く
if (reply.visibility === 'followers' && !Object.hasOwn(this.following, reply.userId)) return;
if (reply.visibility === 'followers' && !Object.hasOwn(this.following, reply.userId) && reply.userId !== this.user!.id) return;
} else {
// 「チャンネル接続主への返信」でもなければ、「チャンネル接続主が行った返信」でもなければ、「投稿者の投稿者自身への返信」でもない場合
if (reply.userId !== this.user!.id && !isMe && reply.userId !== note.userId) return;
@@ -73,7 +73,7 @@ class HomeTimelineChannel extends Channel {
if (note.renote.reply) {
const reply = note.renote.reply;
// 自分のフォローしていないユーザーの visibility: followers な投稿への返信のリノートは弾く
if (reply.visibility === 'followers' && !Object.hasOwn(this.following, reply.userId)) return;
if (reply.visibility === 'followers' && !Object.hasOwn(this.following, reply.userId) && reply.userId !== this.user!.id) return;
}
}

View File

@@ -76,14 +76,22 @@ class HybridTimelineChannel extends Channel {
const reply = note.reply;
if ((this.following[note.userId]?.withReplies ?? false) || this.withReplies) {
// 自分のフォローしていないユーザーの visibility: followers な投稿への返信は弾く
if (reply.visibility === 'followers' && !Object.hasOwn(this.following, reply.userId)) return;
if (reply.visibility === 'followers' && !Object.hasOwn(this.following, reply.userId) && reply.userId !== this.user!.id) return;
} else {
// 「チャンネル接続主への返信」でもなければ、「チャンネル接続主が行った返信」でもなければ、「投稿者の投稿者自身への返信」でもない場合
if (reply.userId !== this.user!.id && !isMe && reply.userId !== note.userId) return;
}
}
if (isRenotePacked(note) && !isQuotePacked(note) && !this.withRenotes) return;
// 純粋なリノート(引用リノートでないリノート)の場合
if (isRenotePacked(note) && !isQuotePacked(note) && note.renote) {
if (!this.withRenotes) return;
if (note.renote.reply) {
const reply = note.renote.reply;
// 自分のフォローしていないユーザーの visibility: followers な投稿への返信のリノートは弾く
if (reply.visibility === 'followers' && !Object.hasOwn(this.following, reply.userId) && reply.userId !== this.user!.id) return;
}
}
if (this.user && note.renoteId && !note.text) {
if (note.renote && Object.keys(note.renote.reactions).length > 0) {