feat: media silence (#13842)

* feat: media silence

* fix: lint

* feat: deny creating custom emoji reaction and using custom emoji from media silenced hosts

* chore: メディアサイレンスの説明にカスタム絵文字の話を追加

* Update locales/ja-JP.yml

Co-authored-by: Sayamame-beans <61457993+Sayamame-beans@users.noreply.github.com>

* chore: update index.d.ts

* docs(changelog): update changelog

---------

Co-authored-by: Sayamame-beans <61457993+Sayamame-beans@users.noreply.github.com>
This commit is contained in:
anatawa12
2024-07-30 19:47:45 +09:00
committed by GitHub
parent 8f40f932e4
commit 5c42a0e439
16 changed files with 124 additions and 11 deletions

View File

@@ -43,6 +43,7 @@ import { RoleService } from '@/core/RoleService.js';
import { correctFilename } from '@/misc/correct-filename.js';
import { isMimeImage } from '@/misc/is-mime-image.js';
import { ModerationLogService } from '@/core/ModerationLogService.js';
import { UtilityService } from '@/core/UtilityService.js';
type AddFileArgs = {
/** User who wish to add file */
@@ -127,6 +128,7 @@ export class DriveService {
private driveChart: DriveChart,
private perUserDriveChart: PerUserDriveChart,
private instanceChart: InstanceChart,
private utilityService: UtilityService,
) {
const logger = new Logger('drive', 'blue');
this.registerLogger = logger.createSubLogger('register', 'yellow');
@@ -587,6 +589,7 @@ export class DriveService {
sensitive ?? false
: false;
if (user && this.utilityService.isMediaSilencedHost(instance.mediaSilencedHosts, user.host)) file.isSensitive = true;
if (info.sensitive && profile!.autoSensitive) file.isSensitive = true;
if (info.sensitive && instance.setSensitiveFlagAutomatically) file.isSensitive = true;
if (userRoleNSFW) file.isSensitive = true;

View File

@@ -364,6 +364,9 @@ export class NoteCreateService implements OnApplicationShutdown {
mentionedUsers = data.apMentions ?? await this.extractMentionedUsers(user, combinedTokens);
}
// if the host is media-silenced, custom emojis are not allowed
if (this.utilityService.isMediaSilencedHost(meta.mediaSilencedHosts, user.host)) emojis = [];
tags = tags.filter(tag => Array.from(tag).length <= 128).splice(0, 32);
if (data.reply && (user.id !== data.reply.userId) && !mentionedUsers.some(u => u.id === data.reply!.userId)) {

View File

@@ -105,6 +105,8 @@ export class ReactionService {
@bindThis
public async create(user: { id: MiUser['id']; host: MiUser['host']; isBot: MiUser['isBot'] }, note: MiNote, _reaction?: string | null) {
const meta = await this.metaService.fetch();
// Check blocking
if (note.userId !== user.id) {
const blocked = await this.userBlockingService.checkBlocked(note.userId, user.id);
@@ -148,6 +150,11 @@ export class ReactionService {
if ((note.reactionAcceptance === 'nonSensitiveOnly' || note.reactionAcceptance === 'nonSensitiveOnlyForLocalLikeOnlyForRemote') && emoji.isSensitive) {
reaction = FALLBACK;
}
// for media silenced host, custom emoji reactions are not allowed
if (reacterHost != null && this.utilityService.isMediaSilencedHost(meta.mediaSilencedHosts, reacterHost)) {
reaction = FALLBACK;
}
} else {
// リアクションとして使う権限がない
reaction = FALLBACK;
@@ -220,8 +227,6 @@ export class ReactionService {
}
}
const meta = await this.metaService.fetch();
if (meta.enableChartsForRemoteUser || (user.host == null)) {
this.perUserReactionsChart.update(user, note);
}

View File

@@ -42,6 +42,12 @@ export class UtilityService {
return silencedHosts.some(x => `.${host.toLowerCase()}`.endsWith(`.${x}`));
}
@bindThis
public isMediaSilencedHost(silencedHosts: string[] | undefined, host: string | null): boolean {
if (!silencedHosts || host == null) return false;
return silencedHosts.some(x => host.toLowerCase() === x);
}
@bindThis
public concatNoteContentsForKeyWordCheck(content: {
cw?: string | null;

View File

@@ -50,6 +50,7 @@ export class InstanceEntityService {
maintainerName: instance.maintainerName,
maintainerEmail: instance.maintainerEmail,
isSilenced: this.utilityService.isSilencedHost(meta.silencedHosts, instance.host),
isMediaSilenced: this.utilityService.isMediaSilencedHost(meta.mediaSilencedHosts, instance.host),
iconUrl: instance.iconUrl,
faviconUrl: instance.faviconUrl,
themeColor: instance.themeColor,