Compare commits

..

No commits in common. "1b19ca47f010e1136ebcc4f88b887ca806db84e2" and "29911226685112ba30bd9c9d7bf9a50fa3eab0fc" have entirely different histories.

12 changed files with 20 additions and 90 deletions

View file

@ -1,6 +1,3 @@
## 2024.9.3 (eGirlskey)
- Blocks are loosened to allow moderators to view posts regardless, as well as allow for seeing parts of threads where you are mentioned
## 2024.9.2 (eGirlskey) ## 2024.9.2 (eGirlskey)
- Improvements to user block: posts should now get properly hidden if they are replies to or mentions of a blocked user. - Improvements to user block: posts should now get properly hidden if they are replies to or mentions of a blocked user.

View file

@ -1,6 +1,6 @@
{ {
"name": "egirlskey", "name": "egirlskey",
"version": "2024.9.3", "version": "2024.9.2",
"codename": "boobdog", "codename": "boobdog",
"repository": { "repository": {
"type": "git", "type": "git",

View file

@ -13,7 +13,6 @@ import type { NotesRepository } from '@/models/_.js';
import { NoteEntityService } from '@/core/entities/NoteEntityService.js'; import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
import { FanoutTimelineName, FanoutTimelineService } from '@/core/FanoutTimelineService.js'; import { FanoutTimelineName, FanoutTimelineService } from '@/core/FanoutTimelineService.js';
import { isUserRelated } from '@/misc/is-user-related.js'; import { isUserRelated } from '@/misc/is-user-related.js';
import { isUserMentioned } from '@/misc/is-user-mentioned.js';
import { isQuote, isRenote } from '@/misc/is-renote.js'; import { isQuote, isRenote } from '@/misc/is-renote.js';
import { CacheService } from '@/core/CacheService.js'; import { CacheService } from '@/core/CacheService.js';
import { isReply } from '@/misc/is-reply.js'; import { isReply } from '@/misc/is-reply.js';
@ -31,7 +30,6 @@ type TimelineOptions = {
alwaysIncludeMyNotes?: boolean; alwaysIncludeMyNotes?: boolean;
ignoreAuthorFromBlock?: boolean; ignoreAuthorFromBlock?: boolean;
ignoreAuthorFromMute?: boolean; ignoreAuthorFromMute?: boolean;
ignoreMentionsFromBlock?: boolean;
excludeNoFiles?: boolean; excludeNoFiles?: boolean;
excludeReplies?: boolean; excludeReplies?: boolean;
excludeBots?: boolean; excludeBots?: boolean;
@ -108,25 +106,17 @@ export class FanoutTimelineEndpointService {
userIdsWhoMeMuting, userIdsWhoMeMuting,
userIdsWhoMeMutingRenotes, userIdsWhoMeMutingRenotes,
userIdsWhoBlockingMe, userIdsWhoBlockingMe,
userIdsWhoMeBlocking,
userMutedInstances, userMutedInstances,
] = await Promise.all([ ] = await Promise.all([
this.cacheService.userMutingsCache.fetch(ps.me.id), this.cacheService.userMutingsCache.fetch(ps.me.id),
this.cacheService.renoteMutingsCache.fetch(ps.me.id), this.cacheService.renoteMutingsCache.fetch(ps.me.id),
this.cacheService.userBlockedCache.fetch(ps.me.id), this.cacheService.userBlockedCache.fetch(ps.me.id),
this.cacheService.userBlockingCache.fetch(ps.me.id),
this.cacheService.userProfileCache.fetch(me.id).then(p => new Set(p.mutedInstances)), this.cacheService.userProfileCache.fetch(me.id).then(p => new Set(p.mutedInstances)),
]); ]);
const parentFilter = filter; const parentFilter = filter;
filter = (note) => { filter = (note) => {
if (isUserRelated(note, userIdsWhoBlockingMe, ps.ignoreAuthorFromBlock)) return false; if (isUserRelated(note, userIdsWhoBlockingMe, ps.ignoreAuthorFromBlock)) return false;
if (isUserRelated(note, userIdsWhoMeBlocking, ps.ignoreAuthorFromBlock)) return false;
const ignoreMentions = ps.ignoreMentionsFromBlock ?? ps.ignoreAuthorFromBlock;
if (ignoreMentions) {
if (isUserMentioned(note, userIdsWhoBlockingMe)) return false;
if (isUserMentioned(note, userIdsWhoMeBlocking)) return false;
}
if (isUserRelated(note, userIdsWhoMeMuting, ps.ignoreAuthorFromMute)) return false; if (isUserRelated(note, userIdsWhoMeMuting, ps.ignoreAuthorFromMute)) return false;
if (!ps.ignoreAuthorFromMute && isRenote(note) && !isQuote(note) && userIdsWhoMeMutingRenotes.has(note.userId)) return false; if (!ps.ignoreAuthorFromMute && isRenote(note) && !isQuote(note) && userIdsWhoMeMutingRenotes.has(note.userId)) return false;
if (isInstanceMuted(note, userMutedInstances)) return false; if (isInstanceMuted(note, userMutedInstances)) return false;

View file

@ -79,7 +79,6 @@ export class QueryService {
.where('blocking.blockeeId = :blockeeId', { blockeeId: me.id }); .where('blocking.blockeeId = :blockeeId', { blockeeId: me.id });
const mentionQuery = `SELECT COUNT(*) FROM unnest(note.mentions) mention WHERE mention IN (${blockingQuery.getQuery()}) OR mention IN (${blockedQuery.getQuery()}) LIMIT 1`; const mentionQuery = `SELECT COUNT(*) FROM unnest(note.mentions) mention WHERE mention IN (${blockingQuery.getQuery()}) OR mention IN (${blockedQuery.getQuery()}) LIMIT 1`;
const mentionMeQuery = `SELECT COUNT(*) FROM unnest(note.mentions) mention WHERE mention = :meId LIMIT 1`;
// 投稿の作者にブロックされていない かつ // 投稿の作者にブロックされていない かつ
// 投稿の返信先の作者にブロックされていない かつ // 投稿の返信先の作者にブロックされていない かつ
@ -99,13 +98,7 @@ export class QueryService {
.orWhere(`note.renoteUserId NOT IN (${ blockedQuery.getQuery() })`) .orWhere(`note.renoteUserId NOT IN (${ blockedQuery.getQuery() })`)
.orWhere(`note.renoteUserId NOT IN (${ blockingQuery.getQuery() })`); .orWhere(`note.renoteUserId NOT IN (${ blockingQuery.getQuery() })`);
})) }))
.andWhere(new Brackets(qb => { .andWhere(`(${mentionQuery}) = 0`);
qb
.where(`(${mentionQuery}) = 0`)
.orWhere('note.userId = :meId', { meId: me.id })
.orWhere('note.replyUserId = :meId', { meId: me.id })
.orWhere(`(${mentionMeQuery}) = 1`, { meId: me.id });
}));
q.setParameters(blockingQuery.getParameters()); q.setParameters(blockingQuery.getParameters());
q.setParameters(blockedQuery.getParameters()); q.setParameters(blockedQuery.getParameters());

View file

@ -236,17 +236,14 @@ export class SearchService {
const [ const [
userIdsWhoMeMuting, userIdsWhoMeMuting,
userIdsWhoBlockingMe, userIdsWhoBlockingMe,
userIdsWhoMeBlocking,
] = me ? await Promise.all([ ] = me ? await Promise.all([
this.cacheService.userMutingsCache.fetch(me.id), this.cacheService.userMutingsCache.fetch(me.id),
this.cacheService.userBlockedCache.fetch(me.id), this.cacheService.userBlockedCache.fetch(me.id),
this.cacheService.userBlockingCache.fetch(me.id),
]) : [new Set<string>(), new Set<string>()]; ]) : [new Set<string>(), new Set<string>()];
const notes = (await this.notesRepository.findBy({ const notes = (await this.notesRepository.findBy({
id: In(res.hits.map(x => x.id)), id: In(res.hits.map(x => x.id)),
})).filter(note => { })).filter(note => {
if (me && isUserRelated(note, userIdsWhoBlockingMe)) return false; if (me && isUserRelated(note, userIdsWhoBlockingMe)) return false;
if (me && isUserRelated(note, userIdsWhoMeBlocking)) return false;
if (me && isUserRelated(note, userIdsWhoMeMuting)) return false; if (me && isUserRelated(note, userIdsWhoMeMuting)) return false;
return true; return true;
}); });

View file

@ -1,20 +0,0 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
export function isUserMentioned(note: any, userIds: Set<string>): boolean {
if (!note) {
return false;
}
if (note.mentions != null && note.mentions.some(mention => userIds.has(mention))) {
return true;
}
if (note.renote != null && note.renote.mentions != null && note.renote.mentions.some(mention => userIds.has(mention))) {
return true;
}
return false;
}

View file

@ -4,6 +4,8 @@
*/ */
export function isUserRelated(note: any, userIds: Set<string>, ignoreAuthor = false): boolean { export function isUserRelated(note: any, userIds: Set<string>, ignoreAuthor = false): boolean {
console.log(note);
if (!note) { if (!note) {
return false; return false;
} }
@ -20,5 +22,13 @@ export function isUserRelated(note: any, userIds: Set<string>, ignoreAuthor = fa
return true; return true;
} }
if (!ignoreAuthor && note.mentions != null && note.mentions.some(mention => userIds.has(mention))) {
return true;
}
if (!ignoreAuthor && note.renote != null && note.renote.mentions != null && note.renote.mentions.some(mention => userIds.has(mention))) {
return true;
}
return false; return false;
} }

View file

@ -10,8 +10,6 @@ import { Endpoint } from '@/server/api/endpoint-base.js';
import { NoteEntityService } from '@/core/entities/NoteEntityService.js'; import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
import { DI } from '@/di-symbols.js'; import { DI } from '@/di-symbols.js';
import { GetterService } from '@/server/api/GetterService.js'; import { GetterService } from '@/server/api/GetterService.js';
import { CacheService } from '@/core/CacheService.js';
import { RoleService } from '@/core/RoleService.js';
import { ApiError } from '../../error.js'; import { ApiError } from '../../error.js';
export const meta = { export const meta = {
@ -57,23 +55,15 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
private noteEntityService: NoteEntityService, private noteEntityService: NoteEntityService,
private getterService: GetterService, private getterService: GetterService,
private cacheService: CacheService,
private roleService: RoleService,
) { ) {
super(meta, paramDef, async (ps, me) => { super(meta, paramDef, async (ps, me) => {
const [userIdsWhoBlockingMe, userIdsWhoMeBlocking, isModerator, note] = await Promise.all([ const note = await this.getterService.getNote(ps.noteId).catch(err => {
me != null && this.cacheService.userBlockedCache.fetch(me.id), if (err.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote);
me != null && this.cacheService.userBlockingCache.fetch(me.id), throw err;
me != null && this.roleService.isModerator(me), });
this.getterService.getNote(ps.noteId).catch(err => {
if (err.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote);
throw err;
}),
]);
const conversation: MiNote[] = []; const conversation: MiNote[] = [];
let i = 0; let i = 0;
let length = 0;
const get = async (id: any) => { const get = async (id: any) => {
i++; i++;
@ -81,17 +71,10 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
if (p == null) return; if (p == null) return;
if (i > ps.offset!) { if (i > ps.offset!) {
if (me == null || conversation.push(p);
isModerator ||
!(userIdsWhoBlockingMe.has(p.userId) || userIdsWhoMeBlocking.has(p.userId))
) {
conversation.push(p);
}
length += 1;
} }
if (length === ps.limit) { if (conversation.length === ps.limit) {
return; return;
} }

View file

@ -10,7 +10,6 @@ import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
import { DI } from '@/di-symbols.js'; import { DI } from '@/di-symbols.js';
import { FeaturedService } from '@/core/FeaturedService.js'; import { FeaturedService } from '@/core/FeaturedService.js';
import { isUserRelated } from '@/misc/is-user-related.js'; import { isUserRelated } from '@/misc/is-user-related.js';
import { isUserMentioned } from '@/misc/is-user-mentioned.js';
import { CacheService } from '@/core/CacheService.js'; import { CacheService } from '@/core/CacheService.js';
export const meta = { export const meta = {
@ -82,11 +81,9 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
const [ const [
userIdsWhoMeMuting, userIdsWhoMeMuting,
userIdsWhoBlockingMe, userIdsWhoBlockingMe,
userIdsWhoMeBlocking,
] = me ? await Promise.all([ ] = me ? await Promise.all([
this.cacheService.userMutingsCache.fetch(me.id), this.cacheService.userMutingsCache.fetch(me.id),
this.cacheService.userBlockedCache.fetch(me.id), this.cacheService.userBlockedCache.fetch(me.id),
this.cacheService.userBlockingCache.fetch(me.id),
]) : [new Set<string>(), new Set<string>()]; ]) : [new Set<string>(), new Set<string>()];
const query = this.notesRepository.createQueryBuilder('note') const query = this.notesRepository.createQueryBuilder('note')
@ -100,12 +97,8 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
const notes = (await query.getMany()).filter(note => { const notes = (await query.getMany()).filter(note => {
if (me && isUserRelated(note, userIdsWhoBlockingMe)) return false; if (me && isUserRelated(note, userIdsWhoBlockingMe)) return false;
if (me && isUserRelated(note, userIdsWhoMeBlocking)) return false;
if (me && isUserRelated(note, userIdsWhoMeMuting)) return false; if (me && isUserRelated(note, userIdsWhoMeMuting)) return false;
if (me && isUserMentioned(note, userIdsWhoBlockingMe)) return false;
if (me && isUserMentioned(note, userIdsWhoMeBlocking)) return false;
return true; return true;
}); });

View file

@ -11,7 +11,6 @@ import { DI } from '@/di-symbols.js';
import { FeaturedService } from '@/core/FeaturedService.js'; import { FeaturedService } from '@/core/FeaturedService.js';
import { CacheService } from '@/core/CacheService.js'; import { CacheService } from '@/core/CacheService.js';
import { isUserRelated } from '@/misc/is-user-related.js'; import { isUserRelated } from '@/misc/is-user-related.js';
import { isUserMentioned } from '@/misc/is-user-mentioned.js';
export const meta = { export const meta = {
tags: ['notes'], tags: ['notes'],
@ -54,10 +53,9 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
) { ) {
super(meta, paramDef, async (ps, me) => { super(meta, paramDef, async (ps, me) => {
const userIdsWhoBlockingMe = me ? await this.cacheService.userBlockedCache.fetch(me.id) : new Set<string>(); const userIdsWhoBlockingMe = me ? await this.cacheService.userBlockedCache.fetch(me.id) : new Set<string>();
const userIdsWhoMeBlocking = me ? await this.cacheService.userBlockingCache.fetch(me.id) : new Set<string>();
// early return if me is blocked by requesting user // early return if me is blocked by requesting user
if (userIdsWhoBlockingMe.has(ps.userId) || userIdsWhoMeBlocking.has(ps.userId)) { if (userIdsWhoBlockingMe.has(ps.userId)) {
return []; return [];
} }
@ -92,9 +90,6 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
if (me && isUserRelated(note, userIdsWhoBlockingMe, false)) return false; if (me && isUserRelated(note, userIdsWhoBlockingMe, false)) return false;
if (me && isUserRelated(note, userIdsWhoMeMuting, true)) return false; if (me && isUserRelated(note, userIdsWhoMeMuting, true)) return false;
if (me && isUserMentioned(note, userIdsWhoBlockingMe)) return false;
if (me && isUserMentioned(note, userIdsWhoMeBlocking)) return false;
return true; return true;
}); });

View file

@ -13,7 +13,6 @@ import { CacheService } from '@/core/CacheService.js';
import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js';
import { RoleService } from '@/core/RoleService.js'; import { RoleService } from '@/core/RoleService.js';
import { isUserRelated } from '@/misc/is-user-related.js'; import { isUserRelated } from '@/misc/is-user-related.js';
import { isUserMentioned } from '@/misc/is-user-mentioned.js';
import { ApiError } from '../../error.js'; import { ApiError } from '../../error.js';
export const meta = { export const meta = {
@ -78,7 +77,6 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
) { ) {
super(meta, paramDef, async (ps, me) => { super(meta, paramDef, async (ps, me) => {
const userIdsWhoBlockingMe = me ? await this.cacheService.userBlockedCache.fetch(me.id) : new Set<string>(); const userIdsWhoBlockingMe = me ? await this.cacheService.userBlockedCache.fetch(me.id) : new Set<string>();
const userIdsWhoMeBlocking = me ? await this.cacheService.userBlockingCache.fetch(me.id) : new Set<string>();
const iAmModerator = me ? await this.roleService.isModerator(me) : false; // Moderators can see reactions of all users const iAmModerator = me ? await this.roleService.isModerator(me) : false; // Moderators can see reactions of all users
if (!iAmModerator) { if (!iAmModerator) {
const user = await this.cacheService.findUserById(ps.userId); const user = await this.cacheService.findUserById(ps.userId);
@ -92,7 +90,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
} }
// early return if me is blocked by requesting user // early return if me is blocked by requesting user
if (userIdsWhoBlockingMe.has(ps.userId) || userIdsWhoMeBlocking.has(ps.userId)) { if (userIdsWhoBlockingMe.has(ps.userId)) {
return []; return [];
} }
} }
@ -113,9 +111,6 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
if (me && isUserRelated(reaction.note, userIdsWhoBlockingMe)) return false; if (me && isUserRelated(reaction.note, userIdsWhoBlockingMe)) return false;
if (me && isUserRelated(reaction.note, userIdsWhoMeMuting)) return false; if (me && isUserRelated(reaction.note, userIdsWhoMeMuting)) return false;
if (me && isUserMentioned(note, userIdsWhoBlockingMe)) return false;
if (me && isUserMentioned(note, userIdsWhoMeBlocking)) return false;
return true; return true;
}); });

View file

@ -6,7 +6,6 @@
import { bindThis } from '@/decorators.js'; import { bindThis } from '@/decorators.js';
import { isInstanceMuted } from '@/misc/is-instance-muted.js'; import { isInstanceMuted } from '@/misc/is-instance-muted.js';
import { isUserRelated } from '@/misc/is-user-related.js'; import { isUserRelated } from '@/misc/is-user-related.js';
import { isUserMentioned } from '@/misc/is-user-mentioned.js';
import { isRenotePacked, isQuotePacked } from '@/misc/is-renote.js'; import { isRenotePacked, isQuotePacked } from '@/misc/is-renote.js';
import type { Packed } from '@/misc/json-schema.js'; import type { Packed } from '@/misc/json-schema.js';
import type { JsonObject, JsonValue } from '@/misc/json-value.js'; import type { JsonObject, JsonValue } from '@/misc/json-value.js';
@ -77,8 +76,6 @@ export default abstract class Channel {
if (isUserRelated(note, this.userIdsWhoBlockingMe)) return true; if (isUserRelated(note, this.userIdsWhoBlockingMe)) return true;
if (isUserRelated(note, this.userIdsWhoMeBlocking)) return true; if (isUserRelated(note, this.userIdsWhoMeBlocking)) return true;
if (isUserMentioned(note, this.userIdsWhoMeBlocking) && !isUserMentioned(note, [ this.user().id ])) return true;
// 流れてきたNoteがリートをミュートしてるユーザが行ったもの // 流れてきたNoteがリートをミュートしてるユーザが行ったもの
if (isRenotePacked(note) && !isQuotePacked(note) && this.userIdsWhoMeMutingRenotes.has(note.user.id)) return true; if (isRenotePacked(note) && !isQuotePacked(note) && this.userIdsWhoMeMutingRenotes.has(note.user.id)) return true;