Modify social timeline to exclude convos with only 1 person I like

This is an attempt at introducing filtering of replies in timeline in the
style of Mastodon or Pleroma's "only replies directed at me or someone I follow".

Currently one way this surely fails is that self-replies by someone I follow in
a conversation solely with someone I don't follow will pass this filter, and
I will see a conversation I don't want to see.

This probably needs more testing to verify that it's doing what's expected of it.
This commit is contained in:
Michał Sidor 2022-06-14 21:02:22 +02:00 committed by Michcio
parent b74c924f66
commit 191b2692d2
6 changed files with 14 additions and 10 deletions

View file

@ -1,7 +1,7 @@
import { Brackets, SelectQueryBuilder } from 'typeorm';
import { User } from '@/models/entities/user.js';
export function generateRepliesQuery(q: SelectQueryBuilder<any>, me?: Pick<User, 'id' | 'showTimelineReplies'> | null) {
export function generateRepliesQuery(q: SelectQueryBuilder<any>, me?: Pick<User, 'id' | 'showTimelineReplies'> | null, followingQuery: SelectQueryBuilder<any> | null) {
if (me == null) {
q.andWhere(new Brackets(qb => { qb
.where('note.replyId IS NULL') // 返信ではない
@ -14,6 +14,7 @@ export function generateRepliesQuery(q: SelectQueryBuilder<any>, me?: Pick<User,
q.andWhere(new Brackets(qb => { qb
.where('note.replyId IS NULL') // 返信ではない
.orWhere('note.replyUserId = :meId', { meId: me.id }) // 返信だけど自分のノートへの返信
.orWhere('note.mentions && array[:meId]::varchar[]', { meId: me.id })
.orWhere(new Brackets(qb => { qb // 返信だけど自分の行った返信
.where('note.replyId IS NOT NULL')
.andWhere('note.userId = :meId', { meId: me.id });
@ -22,6 +23,12 @@ export function generateRepliesQuery(q: SelectQueryBuilder<any>, me?: Pick<User,
.where('note.replyId IS NOT NULL')
.andWhere('note.replyUserId = note.userId');
}));
if (followingQuery !== null) {
qb.orWhere(new Brackets(qb => { qb
.where(`note.mentions && array(${ followingQuery.getQuery() })`)
.setParameters(followingQuery.getParameters())
}))
}
}));
}
}

View file

@ -75,7 +75,7 @@ export default define(meta, paramDef, async (ps, user) => {
.leftJoinAndSelect('renoteUser.avatar', 'renoteUserAvatar')
.leftJoinAndSelect('renoteUser.banner', 'renoteUserBanner');
generateRepliesQuery(query, user);
generateRepliesQuery(query, user, null);
if (user) {
generateMutedUserQuery(query, user);
generateMutedNoteQuery(query, user);

View file

@ -89,7 +89,7 @@ export default define(meta, paramDef, async (ps, user) => {
.setParameters(followingQuery.getParameters());
generateChannelQuery(query, user);
generateRepliesQuery(query, user);
generateRepliesQuery(query, user, followingQuery);
generateVisibilityQuery(query, user);
generateMutedUserQuery(query, user);
generateMutedNoteQuery(query, user);

View file

@ -82,7 +82,7 @@ export default define(meta, paramDef, async (ps, user) => {
.leftJoinAndSelect('renoteUser.banner', 'renoteUserBanner');
generateChannelQuery(query, user);
generateRepliesQuery(query, user);
generateRepliesQuery(query, user, null);
generateVisibilityQuery(query, user);
if (user) generateMutedUserQuery(query, user);
if (user) generateMutedNoteQuery(query, user);

View file

@ -81,7 +81,7 @@ export default define(meta, paramDef, async (ps, user) => {
.setParameters(followingQuery.getParameters());
generateChannelQuery(query, user);
generateRepliesQuery(query, user);
generateRepliesQuery(query, user, followingQuery);
generateVisibilityQuery(query, user);
generateMutedUserQuery(query, user);
generateMutedNoteQuery(query, user);

View file

@ -40,11 +40,8 @@ export default class extends Channel {
// Ignore notes from instances the user has muted
if (isInstanceMuted(note, new Set<string>(this.userProfile?.mutedInstances ?? []))) return;
// 関係ない返信は除外
if (note.reply && !this.user!.showTimelineReplies) {
const reply = note.reply;
// 「チャンネル接続主への返信」でもなければ、「チャンネル接続主が行った返信」でもなければ、「投稿者の投稿者自身への返信」でもない場合
if (reply.userId !== this.user!.id && note.userId !== this.user!.id && reply.userId !== note.userId) return;
if (note.reply && note.mentions && !this.user!.showTimelineReplies) {
if (!note.mentions.includes(this.user!.id) && !note.mentions.some((user: string) => this.following.has(user))) return;
}
// 流れてきたNoteがミュートしているユーザーが関わるものだったら無視する