replace "Mark instance as NSFW" toggle with an instance-level mandatory CW
This commit is contained in:
parent
604f5a5c68
commit
d62be884b3
24 changed files with 44 additions and 127 deletions
|
|
@ -1,6 +1,18 @@
|
||||||
# Upgrade Notes
|
# Upgrade Notes
|
||||||
|
|
||||||
## 2025.X.X
|
## 2025.5.2
|
||||||
|
|
||||||
|
### Mark instance as NSFW
|
||||||
|
|
||||||
|
The "Mark instance as NSFW" has been removed in favor of the new "mandatory CW" / "force CW" system.
|
||||||
|
Moderators can now apply any Content Warning of their choice to all notes from an instance by populating the "Force content warning" field on that instance's info page.
|
||||||
|
The new Content Warning applies immediately, is retroactive, and does not federate or "infect" replies in a thread.
|
||||||
|
|
||||||
|
The upgrade will automatically a content warning of "NSFW" for instances that were formerly marked as NSFW, which displays as `[instance name] is flagged: "NSFW"` to users.
|
||||||
|
The `notes` table is also cleaned up to remove any leftover "Instance is marked as NSFW" content warnings from posts.
|
||||||
|
Staff can then remove or modify the new CW as usual.
|
||||||
|
|
||||||
|
## 2025.2.2
|
||||||
|
|
||||||
### Authorized Fetch
|
### Authorized Fetch
|
||||||
|
|
||||||
|
|
@ -13,6 +25,8 @@ Do not remove it before migration, or else the setting will reset to default (di
|
||||||
|
|
||||||
### Hellspawns
|
### Hellspawns
|
||||||
|
|
||||||
|
**Note: this workaround is no longer needed on Sharkey version 2025.5.2 and later, as "Mark instance as NSFW" has been completely rewritten.**
|
||||||
|
|
||||||
Sharkey versions before 2024.10 suffered from a bug in the "Mark instance as NSFW" feature.
|
Sharkey versions before 2024.10 suffered from a bug in the "Mark instance as NSFW" feature.
|
||||||
When a user from such an instance boosted a note, the boost would be converted to a hellspawn (pure renote with Content Warning).
|
When a user from such an instance boosted a note, the boost would be converted to a hellspawn (pure renote with Content Warning).
|
||||||
Hellspawns are buggy and do not properly federate, so it may be desirable to correct any that already exist in the database.
|
Hellspawns are buggy and do not properly federate, so it may be desirable to correct any that already exist in the database.
|
||||||
|
|
|
||||||
8
locales/index.d.ts
vendored
8
locales/index.d.ts
vendored
|
|
@ -10964,14 +10964,6 @@ export interface Locale extends ILocale {
|
||||||
* Set content warning for instance
|
* Set content warning for instance
|
||||||
*/
|
*/
|
||||||
"setMandatoryCWForInstance": string;
|
"setMandatoryCWForInstance": string;
|
||||||
/**
|
|
||||||
* Set remote instance as NSFW
|
|
||||||
*/
|
|
||||||
"setRemoteInstanceNSFW": string;
|
|
||||||
/**
|
|
||||||
* Unset remote instance as NSFW
|
|
||||||
*/
|
|
||||||
"unsetRemoteInstanceNSFW": string;
|
|
||||||
/**
|
/**
|
||||||
* Rejected reports from remote instance
|
* Rejected reports from remote instance
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: hazelnoot and other Sharkey contributors
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
export class ReplaceInstanceIsNSFW1751236746539 {
|
||||||
|
name = 'ReplaceInstanceIsNSFW1751236746539'
|
||||||
|
|
||||||
|
async up(queryRunner) {
|
||||||
|
// Data migration
|
||||||
|
await queryRunner.query(`UPDATE "instance" SET "mandatoryCW" = 'NSFW' WHERE "isNSFW" = true`);
|
||||||
|
await queryRunner.query(`UPDATE "note" SET "cw" = null WHERE "cw" = 'Instance is marked as NSFW'`);
|
||||||
|
|
||||||
|
// Schema migration
|
||||||
|
await queryRunner.query(`ALTER TABLE "instance" DROP COLUMN "isNSFW"`);
|
||||||
|
}
|
||||||
|
|
||||||
|
async down(queryRunner) {
|
||||||
|
// Schema migration
|
||||||
|
await queryRunner.query(`ALTER TABLE "instance" ADD "isNSFW" boolean NOT NULL DEFAULT false`);
|
||||||
|
|
||||||
|
// Data migration
|
||||||
|
await queryRunner.query(`UPDATE "instance" SET "isNSFW" = true WHERE "mandatoryCW" ILIKE '%NSFW%'`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -414,14 +414,6 @@ export class NoteCreateService implements OnApplicationShutdown {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (user.host && !data.cw) {
|
|
||||||
await this.federatedInstanceService.fetchOrRegister(user.host).then(async i => {
|
|
||||||
if (i.isNSFW && !this.isPureRenote(data)) {
|
|
||||||
data.cw = 'Instance is marked as NSFW';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mentionedUsers.length > 0 && mentionedUsers.length > (await this.roleService.getUserPolicies(user.id)).mentionLimit) {
|
if (mentionedUsers.length > 0 && mentionedUsers.length > (await this.roleService.getUserPolicies(user.id)).mentionLimit) {
|
||||||
throw new IdentifiableError('9f466dab-c856-48cd-9e65-ff90ff750580', 'Note contains too many mentions');
|
throw new IdentifiableError('9f466dab-c856-48cd-9e65-ff90ff750580', 'Note contains too many mentions');
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -443,14 +443,6 @@ export class NoteEditService implements OnApplicationShutdown {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (user.host && !data.cw) {
|
|
||||||
await this.federatedInstanceService.fetchOrRegister(user.host).then(async i => {
|
|
||||||
if (i.isNSFW && !this.noteCreateService.isPureRenote(data)) {
|
|
||||||
data.cw = 'Instance is marked as NSFW';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mentionedUsers.length > 0 && mentionedUsers.length > (await this.roleService.getUserPolicies(user.id)).mentionLimit) {
|
if (mentionedUsers.length > 0 && mentionedUsers.length > (await this.roleService.getUserPolicies(user.id)).mentionLimit) {
|
||||||
throw new IdentifiableError('9f466dab-c856-48cd-9e65-ff90ff750580', 'Note contains too many mentions');
|
throw new IdentifiableError('9f466dab-c856-48cd-9e65-ff90ff750580', 'Note contains too many mentions');
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -75,7 +75,7 @@ export class ApImageService {
|
||||||
const shouldBeCached = this.meta.cacheRemoteFiles && (this.meta.cacheRemoteSensitiveFiles || !image.sensitive);
|
const shouldBeCached = this.meta.cacheRemoteFiles && (this.meta.cacheRemoteSensitiveFiles || !image.sensitive);
|
||||||
|
|
||||||
await this.federatedInstanceService.fetchOrRegister(actor.host).then(async i => {
|
await this.federatedInstanceService.fetchOrRegister(actor.host).then(async i => {
|
||||||
if (i.isNSFW) {
|
if (i.isMediaSilenced) {
|
||||||
image.sensitive = true;
|
image.sensitive = true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,6 @@ export class InstanceEntityService {
|
||||||
themeColor: instance.themeColor,
|
themeColor: instance.themeColor,
|
||||||
infoUpdatedAt: instance.infoUpdatedAt ? instance.infoUpdatedAt.toISOString() : null,
|
infoUpdatedAt: instance.infoUpdatedAt ? instance.infoUpdatedAt.toISOString() : null,
|
||||||
latestRequestReceivedAt: instance.latestRequestReceivedAt ? instance.latestRequestReceivedAt.toISOString() : null,
|
latestRequestReceivedAt: instance.latestRequestReceivedAt ? instance.latestRequestReceivedAt.toISOString() : null,
|
||||||
isNSFW: instance.isNSFW,
|
|
||||||
rejectReports: instance.rejectReports,
|
rejectReports: instance.rejectReports,
|
||||||
rejectQuotes: instance.rejectQuotes,
|
rejectQuotes: instance.rejectQuotes,
|
||||||
moderationNote: iAmModerator ? instance.moderationNote : null,
|
moderationNote: iAmModerator ? instance.moderationNote : null,
|
||||||
|
|
|
||||||
|
|
@ -205,11 +205,6 @@ export class MiInstance {
|
||||||
})
|
})
|
||||||
public infoUpdatedAt: Date | null;
|
public infoUpdatedAt: Date | null;
|
||||||
|
|
||||||
@Column('boolean', {
|
|
||||||
default: false,
|
|
||||||
})
|
|
||||||
public isNSFW: boolean;
|
|
||||||
|
|
||||||
@Column('boolean', {
|
@Column('boolean', {
|
||||||
default: false,
|
default: false,
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -116,11 +116,6 @@ export const packedFederationInstanceSchema = {
|
||||||
optional: false, nullable: true,
|
optional: false, nullable: true,
|
||||||
format: 'date-time',
|
format: 'date-time',
|
||||||
},
|
},
|
||||||
isNSFW: {
|
|
||||||
type: 'boolean',
|
|
||||||
optional: false,
|
|
||||||
nullable: false,
|
|
||||||
},
|
|
||||||
rejectReports: {
|
rejectReports: {
|
||||||
type: 'boolean',
|
type: 'boolean',
|
||||||
optional: false,
|
optional: false,
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,6 @@ export const paramDef = {
|
||||||
properties: {
|
properties: {
|
||||||
host: { type: 'string' },
|
host: { type: 'string' },
|
||||||
isSuspended: { type: 'boolean' },
|
isSuspended: { type: 'boolean' },
|
||||||
isNSFW: { type: 'boolean' },
|
|
||||||
rejectReports: { type: 'boolean' },
|
rejectReports: { type: 'boolean' },
|
||||||
moderationNote: { type: 'string' },
|
moderationNote: { type: 'string' },
|
||||||
rejectQuotes: { type: 'boolean' },
|
rejectQuotes: { type: 'boolean' },
|
||||||
|
|
@ -58,7 +57,6 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
||||||
|
|
||||||
await this.federatedInstanceService.update(instance.id, {
|
await this.federatedInstanceService.update(instance.id, {
|
||||||
suspensionState,
|
suspensionState,
|
||||||
isNSFW: ps.isNSFW,
|
|
||||||
rejectReports: ps.rejectReports,
|
rejectReports: ps.rejectReports,
|
||||||
rejectQuotes: ps.rejectQuotes,
|
rejectQuotes: ps.rejectQuotes,
|
||||||
moderationNote: ps.moderationNote,
|
moderationNote: ps.moderationNote,
|
||||||
|
|
@ -78,14 +76,6 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ps.isNSFW != null && instance.isNSFW !== ps.isNSFW) {
|
|
||||||
const message = ps.rejectReports ? 'setRemoteInstanceNSFW' : 'unsetRemoteInstanceNSFW';
|
|
||||||
this.moderationLogService.log(me, message, {
|
|
||||||
id: instance.id,
|
|
||||||
host: instance.host,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ps.rejectReports != null && instance.rejectReports !== ps.rejectReports) {
|
if (ps.rejectReports != null && instance.rejectReports !== ps.rejectReports) {
|
||||||
const message = ps.rejectReports ? 'rejectRemoteInstanceReports' : 'acceptRemoteInstanceReports';
|
const message = ps.rejectReports ? 'rejectRemoteInstanceReports' : 'acceptRemoteInstanceReports';
|
||||||
this.moderationLogService.log(me, message, {
|
this.moderationLogService.log(me, message, {
|
||||||
|
|
|
||||||
|
|
@ -108,8 +108,6 @@ export const moderationLogTypes = [
|
||||||
'setMandatoryCW',
|
'setMandatoryCW',
|
||||||
'setMandatoryCWForNote',
|
'setMandatoryCWForNote',
|
||||||
'setMandatoryCWForInstance',
|
'setMandatoryCWForInstance',
|
||||||
'setRemoteInstanceNSFW',
|
|
||||||
'unsetRemoteInstanceNSFW',
|
|
||||||
'suspendRemoteInstance',
|
'suspendRemoteInstance',
|
||||||
'unsuspendRemoteInstance',
|
'unsuspendRemoteInstance',
|
||||||
'rejectRemoteInstanceReports',
|
'rejectRemoteInstanceReports',
|
||||||
|
|
@ -309,14 +307,6 @@ export type ModerationLogPayloads = {
|
||||||
oldCW: string | null;
|
oldCW: string | null;
|
||||||
host: string;
|
host: string;
|
||||||
};
|
};
|
||||||
setRemoteInstanceNSFW: {
|
|
||||||
id: string;
|
|
||||||
host: string;
|
|
||||||
};
|
|
||||||
unsetRemoteInstanceNSFW: {
|
|
||||||
id: string;
|
|
||||||
host: string;
|
|
||||||
};
|
|
||||||
suspendRemoteInstance: {
|
suspendRemoteInstance: {
|
||||||
id: string;
|
id: string;
|
||||||
host: string;
|
host: string;
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,6 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<option value="subscribing">{{ i18n.ts.subscribing }}</option>
|
<option value="subscribing">{{ i18n.ts.subscribing }}</option>
|
||||||
<option value="publishing">{{ i18n.ts.publishing }}</option>
|
<option value="publishing">{{ i18n.ts.publishing }}</option>
|
||||||
<option value="bubble">Bubble</option>
|
<option value="bubble">Bubble</option>
|
||||||
<option value="nsfw">NSFW</option>
|
|
||||||
<option v-if="$i" value="suspended">{{ i18n.ts.suspended }}</option>
|
<option v-if="$i" value="suspended">{{ i18n.ts.suspended }}</option>
|
||||||
<option v-if="$i" value="silenced">{{ i18n.ts.silence }}</option>
|
<option v-if="$i" value="silenced">{{ i18n.ts.silence }}</option>
|
||||||
<option v-if="$i" value="blocked">{{ i18n.ts.blocked }}</option>
|
<option v-if="$i" value="blocked">{{ i18n.ts.blocked }}</option>
|
||||||
|
|
@ -83,18 +82,16 @@ const pagination = {
|
||||||
state.value === 'blocked' ? { blocked: true } :
|
state.value === 'blocked' ? { blocked: true } :
|
||||||
state.value === 'silenced' ? { silenced: true } :
|
state.value === 'silenced' ? { silenced: true } :
|
||||||
state.value === 'notResponding' ? { notResponding: true } :
|
state.value === 'notResponding' ? { notResponding: true } :
|
||||||
state.value === 'nsfw' ? { nsfw: true } :
|
|
||||||
state.value === 'bubble' ? { bubble: true } :
|
state.value === 'bubble' ? { bubble: true } :
|
||||||
{}),
|
{}),
|
||||||
})),
|
})),
|
||||||
} as Paging;
|
} satisfies Paging;
|
||||||
|
|
||||||
function getStatus(instance) {
|
function getStatus(instance) {
|
||||||
if (instance.isSuspended) return 'Suspended';
|
if (instance.isSuspended) return 'Suspended';
|
||||||
if (instance.isBlocked) return 'Blocked';
|
if (instance.isBlocked) return 'Blocked';
|
||||||
if (instance.isSilenced) return 'Silenced';
|
if (instance.isSilenced) return 'Silenced';
|
||||||
if (instance.isNotResponding) return 'Error';
|
if (instance.isNotResponding) return 'Error';
|
||||||
if (instance.isNSFW) return 'NSFW';
|
|
||||||
return 'Alive';
|
return 'Alive';
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -19,8 +19,6 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<option value="federating">{{ i18n.ts.federating }}</option>
|
<option value="federating">{{ i18n.ts.federating }}</option>
|
||||||
<option value="subscribing">{{ i18n.ts.subscribing }}</option>
|
<option value="subscribing">{{ i18n.ts.subscribing }}</option>
|
||||||
<option value="publishing">{{ i18n.ts.publishing }}</option>
|
<option value="publishing">{{ i18n.ts.publishing }}</option>
|
||||||
<!-- TODO translate -->
|
|
||||||
<option value="nsfw">NSFW</option>
|
|
||||||
<option value="suspended">{{ i18n.ts.suspended }}</option>
|
<option value="suspended">{{ i18n.ts.suspended }}</option>
|
||||||
<option value="blocked">{{ i18n.ts.blocked }}</option>
|
<option value="blocked">{{ i18n.ts.blocked }}</option>
|
||||||
<option value="silenced">{{ i18n.ts.silence }}</option>
|
<option value="silenced">{{ i18n.ts.silence }}</option>
|
||||||
|
|
@ -85,7 +83,6 @@ const pagination = {
|
||||||
state.value === 'blocked' ? { blocked: true } :
|
state.value === 'blocked' ? { blocked: true } :
|
||||||
state.value === 'silenced' ? { silenced: true } :
|
state.value === 'silenced' ? { silenced: true } :
|
||||||
state.value === 'notResponding' ? { notResponding: true } :
|
state.value === 'notResponding' ? { notResponding: true } :
|
||||||
state.value === 'nsfw' ? { nsfw: true } :
|
|
||||||
{}),
|
{}),
|
||||||
})),
|
})),
|
||||||
};
|
};
|
||||||
|
|
@ -104,7 +101,6 @@ function getStatus(instance: Misskey.entities.FederationInstance) {
|
||||||
if (instance.isBlocked) return 'Blocked';
|
if (instance.isBlocked) return 'Blocked';
|
||||||
if (instance.isSilenced) return 'Silenced';
|
if (instance.isSilenced) return 'Silenced';
|
||||||
if (instance.isNotResponding) return 'Error';
|
if (instance.isNotResponding) return 'Error';
|
||||||
if (instance.isNSFW) return 'NSFW';
|
|
||||||
return 'Alive';
|
return 'Alive';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,8 +30,6 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
'setMandatoryCWForNote',
|
'setMandatoryCWForNote',
|
||||||
'setMandatoryCWForInstance',
|
'setMandatoryCWForInstance',
|
||||||
'suspendRemoteInstance',
|
'suspendRemoteInstance',
|
||||||
'setRemoteInstanceNSFW',
|
|
||||||
'unsetRemoteInstanceNSFW',
|
|
||||||
'rejectRemoteInstanceReports',
|
'rejectRemoteInstanceReports',
|
||||||
'acceptRemoteInstanceReports',
|
'acceptRemoteInstanceReports',
|
||||||
'rejectQuotesUser',
|
'rejectQuotesUser',
|
||||||
|
|
@ -69,7 +67,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
'removeRelay',
|
'removeRelay',
|
||||||
].includes(log.type)
|
].includes(log.type)
|
||||||
}"
|
}"
|
||||||
>{{ i18n.ts._moderationLogTypes[log.type] }}</b>
|
>{{ i18n.ts._moderationLogTypes[log.type] ?? log.type }}</b>
|
||||||
<span v-if="log.type === 'updateUserNote'">: @{{ log.info.userUsername }}{{ log.info.userHost ? '@' + log.info.userHost : '' }}</span>
|
<span v-if="log.type === 'updateUserNote'">: @{{ log.info.userUsername }}{{ log.info.userHost ? '@' + log.info.userHost : '' }}</span>
|
||||||
<span v-else-if="log.type === 'suspend'">: @{{ log.info.userUsername }}{{ log.info.userHost ? '@' + log.info.userHost : '' }}</span>
|
<span v-else-if="log.type === 'suspend'">: @{{ log.info.userUsername }}{{ log.info.userHost ? '@' + log.info.userHost : '' }}</span>
|
||||||
<span v-else-if="log.type === 'approve'">: @{{ log.info.userUsername }}{{ log.info.userHost ? '@' + log.info.userHost : '' }}</span>
|
<span v-else-if="log.type === 'approve'">: @{{ log.info.userUsername }}{{ log.info.userHost ? '@' + log.info.userHost : '' }}</span>
|
||||||
|
|
@ -95,8 +93,6 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<span v-else-if="log.type === 'unmarkSensitiveDriveFile'">: @{{ log.info.fileUserUsername }}{{ log.info.fileUserHost ? '@' + log.info.fileUserHost : '' }}</span>
|
<span v-else-if="log.type === 'unmarkSensitiveDriveFile'">: @{{ log.info.fileUserUsername }}{{ log.info.fileUserHost ? '@' + log.info.fileUserHost : '' }}</span>
|
||||||
<span v-else-if="log.type === 'suspendRemoteInstance'">: {{ log.info.host }}</span>
|
<span v-else-if="log.type === 'suspendRemoteInstance'">: {{ log.info.host }}</span>
|
||||||
<span v-else-if="log.type === 'unsuspendRemoteInstance'">: {{ log.info.host }}</span>
|
<span v-else-if="log.type === 'unsuspendRemoteInstance'">: {{ log.info.host }}</span>
|
||||||
<span v-else-if="log.type === 'setRemoteInstanceNSFW'">: {{ log.info.host }}</span>
|
|
||||||
<span v-else-if="log.type === 'unsetRemoteInstanceNSFW'">: {{ log.info.host }}</span>
|
|
||||||
<span v-else-if="log.type === 'rejectRemoteInstanceReports'">: {{ log.info.host }}</span>
|
<span v-else-if="log.type === 'rejectRemoteInstanceReports'">: {{ log.info.host }}</span>
|
||||||
<span v-else-if="log.type === 'acceptRemoteInstanceReports'">: {{ log.info.host }}</span>
|
<span v-else-if="log.type === 'acceptRemoteInstanceReports'">: {{ log.info.host }}</span>
|
||||||
<span v-else-if="log.type === 'createGlobalAnnouncement'">: {{ log.info.announcement.title }}</span>
|
<span v-else-if="log.type === 'createGlobalAnnouncement'">: {{ log.info.announcement.title }}</span>
|
||||||
|
|
|
||||||
|
|
@ -118,7 +118,6 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<MkInfo v-if="isBaseBlocked" warn>{{ i18n.ts.blockedByBase }}</MkInfo>
|
<MkInfo v-if="isBaseBlocked" warn>{{ i18n.ts.blockedByBase }}</MkInfo>
|
||||||
<MkSwitch v-model="isBlocked" :disabled="!meta || !instance || isBaseBlocked" @update:modelValue="toggleBlock">{{ i18n.ts.blockThisInstance }}</MkSwitch>
|
<MkSwitch v-model="isBlocked" :disabled="!meta || !instance || isBaseBlocked" @update:modelValue="toggleBlock">{{ i18n.ts.blockThisInstance }}</MkSwitch>
|
||||||
<MkSwitch v-model="rejectQuotes" :disabled="!instance" @update:modelValue="toggleRejectQuotes">{{ i18n.ts.rejectQuotesInstance }}</MkSwitch>
|
<MkSwitch v-model="rejectQuotes" :disabled="!instance" @update:modelValue="toggleRejectQuotes">{{ i18n.ts.rejectQuotesInstance }}</MkSwitch>
|
||||||
<MkSwitch v-model="isNSFW" :disabled="!instance" @update:modelValue="toggleNSFW">{{ i18n.ts.markInstanceAsNSFW }}</MkSwitch>
|
|
||||||
<MkSwitch v-model="rejectReports" :disabled="!instance" @update:modelValue="toggleRejectReports">{{ i18n.ts.rejectReports }}</MkSwitch>
|
<MkSwitch v-model="rejectReports" :disabled="!instance" @update:modelValue="toggleRejectReports">{{ i18n.ts.rejectReports }}</MkSwitch>
|
||||||
<MkInfo v-if="isBaseMediaSilenced" warn>{{ i18n.ts.mediaSilencedByBase }}</MkInfo>
|
<MkInfo v-if="isBaseMediaSilenced" warn>{{ i18n.ts.mediaSilencedByBase }}</MkInfo>
|
||||||
<MkSwitch v-model="isMediaSilenced" :disabled="!meta || !instance || isBaseMediaSilenced" @update:modelValue="toggleMediaSilenced">{{ i18n.ts.mediaSilenceThisInstance }}</MkSwitch>
|
<MkSwitch v-model="isMediaSilenced" :disabled="!meta || !instance || isBaseMediaSilenced" @update:modelValue="toggleMediaSilenced">{{ i18n.ts.mediaSilenceThisInstance }}</MkSwitch>
|
||||||
|
|
@ -259,7 +258,6 @@ const suspensionState = ref<'none' | 'manuallySuspended' | 'goneSuspended' | 'au
|
||||||
const isSuspended = ref(false);
|
const isSuspended = ref(false);
|
||||||
const isBlocked = ref(false);
|
const isBlocked = ref(false);
|
||||||
const isSilenced = ref(false);
|
const isSilenced = ref(false);
|
||||||
const isNSFW = ref(false);
|
|
||||||
const rejectQuotes = ref(false);
|
const rejectQuotes = ref(false);
|
||||||
const rejectReports = ref(false);
|
const rejectReports = ref(false);
|
||||||
const isMediaSilenced = ref(false);
|
const isMediaSilenced = ref(false);
|
||||||
|
|
@ -320,13 +318,6 @@ const badges = computed(() => {
|
||||||
style: 'warning',
|
style: 'warning',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (instance.value.isNSFW) {
|
|
||||||
arr.push({
|
|
||||||
key: 'nsfw',
|
|
||||||
label: i18n.ts.nsfw,
|
|
||||||
style: 'warning',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (instance.value.isBubbled) {
|
if (instance.value.isBubbled) {
|
||||||
arr.push({
|
arr.push({
|
||||||
key: 'bubbled',
|
key: 'bubbled',
|
||||||
|
|
@ -404,7 +395,6 @@ async function fetch(withHint = false): Promise<void> {
|
||||||
isSuspended.value = suspensionState.value !== 'none';
|
isSuspended.value = suspensionState.value !== 'none';
|
||||||
isBlocked.value = instance.value?.isBlocked ?? false;
|
isBlocked.value = instance.value?.isBlocked ?? false;
|
||||||
isSilenced.value = instance.value?.isSilenced ?? false;
|
isSilenced.value = instance.value?.isSilenced ?? false;
|
||||||
isNSFW.value = instance.value?.isNSFW ?? false;
|
|
||||||
rejectReports.value = instance.value?.rejectReports ?? false;
|
rejectReports.value = instance.value?.rejectReports ?? false;
|
||||||
rejectQuotes.value = instance.value?.rejectQuotes ?? false;
|
rejectQuotes.value = instance.value?.rejectQuotes ?? false;
|
||||||
isMediaSilenced.value = instance.value?.isMediaSilenced ?? false;
|
isMediaSilenced.value = instance.value?.isMediaSilenced ?? false;
|
||||||
|
|
@ -470,18 +460,6 @@ async function toggleSuspended(): Promise<void> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function toggleNSFW(): Promise<void> {
|
|
||||||
if (!iAmModerator) return;
|
|
||||||
await os.promiseDialog(async () => {
|
|
||||||
if (!instance.value) throw new Error('No instance?');
|
|
||||||
await misskeyApi('admin/federation/update-instance', {
|
|
||||||
host: instance.value.host,
|
|
||||||
isNSFW: isNSFW.value,
|
|
||||||
});
|
|
||||||
await fetch();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async function toggleRejectReports(): Promise<void> {
|
async function toggleRejectReports(): Promise<void> {
|
||||||
if (!iAmModerator) return;
|
if (!iAmModerator) return;
|
||||||
await os.promiseDialog(async () => {
|
await os.promiseDialog(async () => {
|
||||||
|
|
|
||||||
|
|
@ -2964,12 +2964,6 @@ type ModerationLog = {
|
||||||
} | {
|
} | {
|
||||||
type: 'setMandatoryCWForInstance';
|
type: 'setMandatoryCWForInstance';
|
||||||
info: ModerationLogPayloads['setMandatoryCWForInstance'];
|
info: ModerationLogPayloads['setMandatoryCWForInstance'];
|
||||||
} | {
|
|
||||||
type: 'setRemoteInstanceNSFW';
|
|
||||||
info: ModerationLogPayloads['setRemoteInstanceNSFW'];
|
|
||||||
} | {
|
|
||||||
type: 'unsetRemoteInstanceNSFW';
|
|
||||||
info: ModerationLogPayloads['unsetRemoteInstanceNSFW'];
|
|
||||||
} | {
|
} | {
|
||||||
type: 'resetPassword';
|
type: 'resetPassword';
|
||||||
info: ModerationLogPayloads['resetPassword'];
|
info: ModerationLogPayloads['resetPassword'];
|
||||||
|
|
@ -3111,7 +3105,7 @@ type ModerationLog = {
|
||||||
});
|
});
|
||||||
|
|
||||||
// @public (undocumented)
|
// @public (undocumented)
|
||||||
export const moderationLogTypes: readonly ["updateServerSettings", "suspend", "approve", "decline", "unsuspend", "updateUserNote", "addCustomEmoji", "updateCustomEmoji", "deleteCustomEmoji", "assignRole", "unassignRole", "createRole", "updateRole", "deleteRole", "clearQueue", "promoteQueue", "deleteDriveFile", "deleteNote", "createGlobalAnnouncement", "createUserAnnouncement", "updateGlobalAnnouncement", "updateUserAnnouncement", "deleteGlobalAnnouncement", "deleteUserAnnouncement", "resetPassword", "setMandatoryCW", "setMandatoryCWForNote", "setMandatoryCWForInstance", "setRemoteInstanceNSFW", "unsetRemoteInstanceNSFW", "suspendRemoteInstance", "unsuspendRemoteInstance", "rejectRemoteInstanceReports", "acceptRemoteInstanceReports", "updateRemoteInstanceNote", "markSensitiveDriveFile", "unmarkSensitiveDriveFile", "resolveAbuseReport", "forwardAbuseReport", "updateAbuseReportNote", "createInvitation", "createAd", "updateAd", "deleteAd", "createAvatarDecoration", "updateAvatarDecoration", "deleteAvatarDecoration", "unsetUserAvatar", "unsetUserBanner", "createSystemWebhook", "updateSystemWebhook", "deleteSystemWebhook", "createAbuseReportNotificationRecipient", "updateAbuseReportNotificationRecipient", "deleteAbuseReportNotificationRecipient", "deleteAccount", "deletePage", "deleteFlash", "deleteGalleryPost", "deleteChatRoom"];
|
export const moderationLogTypes: readonly ["updateServerSettings", "suspend", "approve", "decline", "unsuspend", "updateUserNote", "addCustomEmoji", "updateCustomEmoji", "deleteCustomEmoji", "assignRole", "unassignRole", "createRole", "updateRole", "deleteRole", "clearQueue", "promoteQueue", "deleteDriveFile", "deleteNote", "createGlobalAnnouncement", "createUserAnnouncement", "updateGlobalAnnouncement", "updateUserAnnouncement", "deleteGlobalAnnouncement", "deleteUserAnnouncement", "resetPassword", "setMandatoryCW", "setMandatoryCWForNote", "setMandatoryCWForInstance", "suspendRemoteInstance", "unsuspendRemoteInstance", "rejectRemoteInstanceReports", "acceptRemoteInstanceReports", "updateRemoteInstanceNote", "markSensitiveDriveFile", "unmarkSensitiveDriveFile", "resolveAbuseReport", "forwardAbuseReport", "updateAbuseReportNote", "createInvitation", "createAd", "updateAd", "deleteAd", "createAvatarDecoration", "updateAvatarDecoration", "deleteAvatarDecoration", "unsetUserAvatar", "unsetUserBanner", "createSystemWebhook", "updateSystemWebhook", "deleteSystemWebhook", "createAbuseReportNotificationRecipient", "updateAbuseReportNotificationRecipient", "deleteAbuseReportNotificationRecipient", "deleteAccount", "deletePage", "deleteFlash", "deleteGalleryPost", "deleteChatRoom"];
|
||||||
|
|
||||||
// @public (undocumented)
|
// @public (undocumented)
|
||||||
type MuteCreateRequest = operations['mute___create']['requestBody']['content']['application/json'];
|
type MuteCreateRequest = operations['mute___create']['requestBody']['content']['application/json'];
|
||||||
|
|
|
||||||
|
|
@ -5346,7 +5346,6 @@ export type components = {
|
||||||
infoUpdatedAt: string | null;
|
infoUpdatedAt: string | null;
|
||||||
/** Format: date-time */
|
/** Format: date-time */
|
||||||
latestRequestReceivedAt: string | null;
|
latestRequestReceivedAt: string | null;
|
||||||
isNSFW: boolean;
|
|
||||||
rejectReports: boolean;
|
rejectReports: boolean;
|
||||||
rejectQuotes: boolean;
|
rejectQuotes: boolean;
|
||||||
moderationNote?: string | null;
|
moderationNote?: string | null;
|
||||||
|
|
@ -8909,7 +8908,6 @@ export type operations = {
|
||||||
'application/json': {
|
'application/json': {
|
||||||
host: string;
|
host: string;
|
||||||
isSuspended?: boolean;
|
isSuspended?: boolean;
|
||||||
isNSFW?: boolean;
|
|
||||||
rejectReports?: boolean;
|
rejectReports?: boolean;
|
||||||
moderationNote?: string;
|
moderationNote?: string;
|
||||||
rejectQuotes?: boolean;
|
rejectQuotes?: boolean;
|
||||||
|
|
|
||||||
|
|
@ -152,8 +152,6 @@ export const moderationLogTypes = [
|
||||||
'setMandatoryCW',
|
'setMandatoryCW',
|
||||||
'setMandatoryCWForNote',
|
'setMandatoryCWForNote',
|
||||||
'setMandatoryCWForInstance',
|
'setMandatoryCWForInstance',
|
||||||
'setRemoteInstanceNSFW',
|
|
||||||
'unsetRemoteInstanceNSFW',
|
|
||||||
'suspendRemoteInstance',
|
'suspendRemoteInstance',
|
||||||
'unsuspendRemoteInstance',
|
'unsuspendRemoteInstance',
|
||||||
'rejectRemoteInstanceReports',
|
'rejectRemoteInstanceReports',
|
||||||
|
|
@ -360,14 +358,6 @@ export type ModerationLogPayloads = {
|
||||||
oldCW: string | null;
|
oldCW: string | null;
|
||||||
host: string;
|
host: string;
|
||||||
};
|
};
|
||||||
setRemoteInstanceNSFW: {
|
|
||||||
id: string;
|
|
||||||
host: string;
|
|
||||||
};
|
|
||||||
unsetRemoteInstanceNSFW: {
|
|
||||||
id: string;
|
|
||||||
host: string;
|
|
||||||
};
|
|
||||||
suspendRemoteInstance: {
|
suspendRemoteInstance: {
|
||||||
id: string;
|
id: string;
|
||||||
host: string;
|
host: string;
|
||||||
|
|
|
||||||
|
|
@ -139,12 +139,6 @@ export type ModerationLog = {
|
||||||
} | {
|
} | {
|
||||||
type: 'setMandatoryCWForInstance';
|
type: 'setMandatoryCWForInstance';
|
||||||
info: ModerationLogPayloads['setMandatoryCWForInstance'];
|
info: ModerationLogPayloads['setMandatoryCWForInstance'];
|
||||||
} | {
|
|
||||||
type: 'setRemoteInstanceNSFW';
|
|
||||||
info: ModerationLogPayloads['setRemoteInstanceNSFW'];
|
|
||||||
} | {
|
|
||||||
type: 'unsetRemoteInstanceNSFW';
|
|
||||||
info: ModerationLogPayloads['unsetRemoteInstanceNSFW'];
|
|
||||||
} | {
|
} | {
|
||||||
type: 'resetPassword';
|
type: 'resetPassword';
|
||||||
info: ModerationLogPayloads['resetPassword'];
|
info: ModerationLogPayloads['resetPassword'];
|
||||||
|
|
|
||||||
|
|
@ -221,8 +221,6 @@ _moderationLogTypes:
|
||||||
approve: "Genehmigt"
|
approve: "Genehmigt"
|
||||||
decline: "Abgelehnt"
|
decline: "Abgelehnt"
|
||||||
setMandatoryCW: "Inhaltswarnung für Benutzer gesetzt"
|
setMandatoryCW: "Inhaltswarnung für Benutzer gesetzt"
|
||||||
setRemoteInstanceNSFW: "Fremde Instanz als NSFW markiert"
|
|
||||||
unsetRemoteInstanceNSFW: "NSFW-Markierung für fremde Instanz entfernt"
|
|
||||||
rejectRemoteInstanceReports: "Meldungen von fremder Instanz abgelehnt"
|
rejectRemoteInstanceReports: "Meldungen von fremder Instanz abgelehnt"
|
||||||
acceptRemoteInstanceReports: "Meldungen von fremder Instanz akzeptiert"
|
acceptRemoteInstanceReports: "Meldungen von fremder Instanz akzeptiert"
|
||||||
rejectQuotesUser: "Zitate von Benutzer gesperrt/entfernt"
|
rejectQuotesUser: "Zitate von Benutzer gesperrt/entfernt"
|
||||||
|
|
|
||||||
|
|
@ -348,8 +348,6 @@ _moderationLogTypes:
|
||||||
setMandatoryCW: "Set content warning for user"
|
setMandatoryCW: "Set content warning for user"
|
||||||
setMandatoryCWForNote: "Set content warning for note"
|
setMandatoryCWForNote: "Set content warning for note"
|
||||||
setMandatoryCWForInstance: "Set content warning for instance"
|
setMandatoryCWForInstance: "Set content warning for instance"
|
||||||
setRemoteInstanceNSFW: "Set remote instance as NSFW"
|
|
||||||
unsetRemoteInstanceNSFW: "Unset remote instance as NSFW"
|
|
||||||
rejectRemoteInstanceReports: "Rejected reports from remote instance"
|
rejectRemoteInstanceReports: "Rejected reports from remote instance"
|
||||||
acceptRemoteInstanceReports: "Accepted reports from remote instance"
|
acceptRemoteInstanceReports: "Accepted reports from remote instance"
|
||||||
rejectQuotesUser: "Blocked/Stripped quote posts from user"
|
rejectQuotesUser: "Blocked/Stripped quote posts from user"
|
||||||
|
|
|
||||||
|
|
@ -277,8 +277,6 @@ _abuseReport:
|
||||||
webhook: "指定したSystemWebhookに通知を送ります(通報を受けた時と通報を解決した時にそれぞれ発信)"
|
webhook: "指定したSystemWebhookに通知を送ります(通報を受けた時と通報を解決した時にそれぞれ発信)"
|
||||||
_moderationLogTypes:
|
_moderationLogTypes:
|
||||||
approve: "承認済み"
|
approve: "承認済み"
|
||||||
setRemoteInstanceNSFW: "Set remote instance as NSFW"
|
|
||||||
unsetRemoteInstanceNSFW: "Set remote instance as NSFW"
|
|
||||||
rejectRemoteInstanceReports: "Rejected reports from remote instance"
|
rejectRemoteInstanceReports: "Rejected reports from remote instance"
|
||||||
acceptRemoteInstanceReports: "Accepted reports from remote instance"
|
acceptRemoteInstanceReports: "Accepted reports from remote instance"
|
||||||
_mfm:
|
_mfm:
|
||||||
|
|
|
||||||
|
|
@ -46,8 +46,6 @@ _moderationLogTypes:
|
||||||
approve: "ที่ได้รับการอนุมัติ"
|
approve: "ที่ได้รับการอนุมัติ"
|
||||||
decline: "ปฏิเสธ"
|
decline: "ปฏิเสธ"
|
||||||
setMandatoryCW: "ตั้งค่าคำเตือนเนื้อหาสำหรับผู้ใช้"
|
setMandatoryCW: "ตั้งค่าคำเตือนเนื้อหาสำหรับผู้ใช้"
|
||||||
setRemoteInstanceNSFW: "ตั้งค่าเซิร์ฟเวอร์ระยะไกลเป็น NSFW"
|
|
||||||
unsetRemoteInstanceNSFW: "ปิดการใช้งานการตั้งค่าเซิร์ฟเวอร์ระยะไกลเป็น NSFW"
|
|
||||||
rejectRemoteInstanceReports: "รายงานถูกปฏิเสธจากเซิร์ฟเวอร์ระยะไกล"
|
rejectRemoteInstanceReports: "รายงานถูกปฏิเสธจากเซิร์ฟเวอร์ระยะไกล"
|
||||||
acceptRemoteInstanceReports: "รายงานได้รับการยอมรับจากเซิร์ฟเวอร์ระยะไกล"
|
acceptRemoteInstanceReports: "รายงานได้รับการยอมรับจากเซิร์ฟเวอร์ระยะไกล"
|
||||||
rejectQuotesUser: "โพสต์คำพูดของผู้ใช้ถูกบล็อค/ลบ"
|
rejectQuotesUser: "โพสต์คำพูดของผู้ใช้ถูกบล็อค/ลบ"
|
||||||
|
|
|
||||||
|
|
@ -41,8 +41,6 @@ _moderationLogTypes:
|
||||||
approve: "Đã chấp thuận"
|
approve: "Đã chấp thuận"
|
||||||
decline: "Từ chối"
|
decline: "Từ chối"
|
||||||
setMandatoryCW: "Đặt cảnh báo nội dung cho người dùng"
|
setMandatoryCW: "Đặt cảnh báo nội dung cho người dùng"
|
||||||
setRemoteInstanceNSFW: "Đặt máy chủ từ xa thành NSFW"
|
|
||||||
unsetRemoteInstanceNSFW: "Hủy cài đặt máy chủ từ xa thành NSFW"
|
|
||||||
rejectRemoteInstanceReports: "Báo cáo bị từ chối từ máy chủ từ xa"
|
rejectRemoteInstanceReports: "Báo cáo bị từ chối từ máy chủ từ xa"
|
||||||
acceptRemoteInstanceReports: "Đã chấp nhận báo cáo từ máy chủ từ xa"
|
acceptRemoteInstanceReports: "Đã chấp nhận báo cáo từ máy chủ từ xa"
|
||||||
rejectQuotesUser: "Đã chặn/Xóa bài đăng trích dẫn của người dùng"
|
rejectQuotesUser: "Đã chặn/Xóa bài đăng trích dẫn của người dùng"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue