add mandatory CW for instances

This commit is contained in:
Hazelnoot 2025-06-27 23:20:59 -04:00
parent 595c004a74
commit 5e0115335a
26 changed files with 282 additions and 8 deletions

View file

@ -34,6 +34,7 @@ export * as 'admin/avatar-decorations/list' from './endpoints/admin/avatar-decor
export * as 'admin/avatar-decorations/update' from './endpoints/admin/avatar-decorations/update.js';
export * as 'admin/captcha/current' from './endpoints/admin/captcha/current.js';
export * as 'admin/captcha/save' from './endpoints/admin/captcha/save.js';
export * as 'admin/cw-instance' from './endpoints/admin/cw-instance.js';
export * as 'admin/cw-note' from './endpoints/admin/cw-note.js';
export * as 'admin/cw-user' from './endpoints/admin/cw-user.js';
export * as 'admin/decline-user' from './endpoints/admin/decline-user.js';

View file

@ -0,0 +1,54 @@
/*
* SPDX-FileCopyrightText: hazelnoot and other Sharkey contributors
* SPDX-License-Identifier: AGPL-3.0-only
*/
import { Injectable } from '@nestjs/common';
import { Endpoint } from '@/server/api/endpoint-base.js';
import { ModerationLogService } from '@/core/ModerationLogService.js';
import { FederatedInstanceService } from '@/core/FederatedInstanceService.js';
export const meta = {
tags: ['admin'],
requireCredential: true,
requireModerator: true,
kind: 'write:admin:cw-instance',
} as const;
export const paramDef = {
type: 'object',
properties: {
host: { type: 'string' },
cw: { type: 'string', nullable: true },
},
required: ['host', 'cw'],
} as const;
@Injectable()
export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-disable-line import/no-default-export
constructor(
private readonly moderationLogService: ModerationLogService,
private readonly federatedInstanceService: FederatedInstanceService,
) {
super(meta, paramDef, async (ps, me) => {
const instance = await this.federatedInstanceService.fetchOrRegister(ps.host);
// Skip if there's nothing to do
if (instance.mandatoryCW === ps.cw) return;
// Log event first.
// This ensures that we don't "lose" the log if an error occurs
await this.moderationLogService.log(me, 'setMandatoryCWForInstance', {
newCW: ps.cw,
oldCW: instance.mandatoryCW,
host: ps.host,
});
await this.federatedInstanceService.update(instance.id, {
// Collapse empty strings to null
mandatoryCW: ps.cw || null,
});
});
}
}

View file

@ -23,6 +23,7 @@ import { MastodonDataService } from '@/server/api/mastodon/MastodonDataService.j
import { GetterService } from '@/server/api/GetterService.js';
import { appendContentWarning } from '@/misc/append-content-warning.js';
import { isRenote } from '@/misc/is-renote.js';
import { FederatedInstanceService } from '@/core/FederatedInstanceService.js';
// Missing from Megalodon apparently
// https://docs.joinmastodon.org/entities/StatusEdit/
@ -68,6 +69,7 @@ export class MastodonConverters {
private readonly idService: IdService,
private readonly driveFileEntityService: DriveFileEntityService,
private readonly mastodonDataService: MastodonDataService,
private readonly federatedInstanceService: FederatedInstanceService,
) {}
private encode(u: MiUser, m: IMentionedRemoteUsers): MastodonEntity.Mention {
@ -210,6 +212,7 @@ export class MastodonConverters {
}
const noteUser = await this.getUser(note.userId);
const noteInstance = noteUser.instance ?? (noteUser.host ? await this.federatedInstanceService.fetch(noteUser.host) : null);
const account = await this.convertAccount(noteUser);
const edits = await this.noteEditRepository.find({ where: { noteId: note.id }, order: { id: 'ASC' } });
const history: StatusEdit[] = [];
@ -231,6 +234,9 @@ export class MastodonConverters {
if (noteUser.mandatoryCW) {
cw = appendContentWarning(cw, noteUser.mandatoryCW);
}
if (noteInstance?.mandatoryCW) {
cw = appendContentWarning(cw, noteInstance.mandatoryCW);
}
const isQuote = renote && (edit.cw || edit.newText || edit.fileIds.length > 0 || note.replyId);
const quoteUri = isQuote