enhance: サーバーごとにモデレーションノートを残せるように
This commit is contained in:
parent
fb0eb5a31f
commit
26c8b53f70
|
@ -14,6 +14,7 @@
|
||||||
## 202x.x.x (unreleased)
|
## 202x.x.x (unreleased)
|
||||||
|
|
||||||
### General
|
### General
|
||||||
|
- Enhance: サーバーごとにモデレーションノートを残せるように
|
||||||
|
|
||||||
### Client
|
### Client
|
||||||
- Enhance: ノート作成画面のファイル添付メニューの区切り線の位置を調整
|
- Enhance: ノート作成画面のファイル添付メニューの区切り線の位置を調整
|
||||||
|
|
|
@ -9172,7 +9172,7 @@ export interface Locale extends ILocale {
|
||||||
*/
|
*/
|
||||||
"updateServerSettings": string;
|
"updateServerSettings": string;
|
||||||
/**
|
/**
|
||||||
* モデレーションノート更新
|
* ユーザーのモデレーションノート更新
|
||||||
*/
|
*/
|
||||||
"updateUserNote": string;
|
"updateUserNote": string;
|
||||||
/**
|
/**
|
||||||
|
@ -9219,6 +9219,10 @@ export interface Locale extends ILocale {
|
||||||
* リモートサーバーを再開
|
* リモートサーバーを再開
|
||||||
*/
|
*/
|
||||||
"unsuspendRemoteInstance": string;
|
"unsuspendRemoteInstance": string;
|
||||||
|
/**
|
||||||
|
* リモートサーバーのモデレーションノート更新
|
||||||
|
*/
|
||||||
|
"updateRemoteInstanceNote": string;
|
||||||
/**
|
/**
|
||||||
* ファイルをセンシティブ付与
|
* ファイルをセンシティブ付与
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -2434,7 +2434,7 @@ _moderationLogTypes:
|
||||||
updateCustomEmoji: "カスタム絵文字更新"
|
updateCustomEmoji: "カスタム絵文字更新"
|
||||||
deleteCustomEmoji: "カスタム絵文字削除"
|
deleteCustomEmoji: "カスタム絵文字削除"
|
||||||
updateServerSettings: "サーバー設定更新"
|
updateServerSettings: "サーバー設定更新"
|
||||||
updateUserNote: "モデレーションノート更新"
|
updateUserNote: "ユーザーのモデレーションノート更新"
|
||||||
deleteDriveFile: "ファイルを削除"
|
deleteDriveFile: "ファイルを削除"
|
||||||
deleteNote: "ノートを削除"
|
deleteNote: "ノートを削除"
|
||||||
createGlobalAnnouncement: "全体のお知らせを作成"
|
createGlobalAnnouncement: "全体のお知らせを作成"
|
||||||
|
@ -2446,6 +2446,7 @@ _moderationLogTypes:
|
||||||
resetPassword: "パスワードをリセット"
|
resetPassword: "パスワードをリセット"
|
||||||
suspendRemoteInstance: "リモートサーバーを停止"
|
suspendRemoteInstance: "リモートサーバーを停止"
|
||||||
unsuspendRemoteInstance: "リモートサーバーを再開"
|
unsuspendRemoteInstance: "リモートサーバーを再開"
|
||||||
|
updateRemoteInstanceNote: "リモートサーバーのモデレーションノート更新"
|
||||||
markSensitiveDriveFile: "ファイルをセンシティブ付与"
|
markSensitiveDriveFile: "ファイルをセンシティブ付与"
|
||||||
unmarkSensitiveDriveFile: "ファイルをセンシティブ解除"
|
unmarkSensitiveDriveFile: "ファイルをセンシティブ解除"
|
||||||
resolveAbuseReport: "通報を解決"
|
resolveAbuseReport: "通報を解決"
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: syuilo and misskey-project
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
export class PerInstanceModNote1708399372194 {
|
||||||
|
name = 'PerInstanceModNote1708399372194'
|
||||||
|
|
||||||
|
async up(queryRunner) {
|
||||||
|
await queryRunner.query(`ALTER TABLE "instance" ADD "moderationNote" character varying(16384) NOT NULL DEFAULT ''`);
|
||||||
|
}
|
||||||
|
|
||||||
|
async down(queryRunner) {
|
||||||
|
await queryRunner.query(`ALTER TABLE "instance" DROP COLUMN "moderationNote"`);
|
||||||
|
}
|
||||||
|
}
|
|
@ -8,12 +8,15 @@ import type { Packed } from '@/misc/json-schema.js';
|
||||||
import type { MiInstance } from '@/models/Instance.js';
|
import type { MiInstance } from '@/models/Instance.js';
|
||||||
import { MetaService } from '@/core/MetaService.js';
|
import { MetaService } from '@/core/MetaService.js';
|
||||||
import { bindThis } from '@/decorators.js';
|
import { bindThis } from '@/decorators.js';
|
||||||
import { UtilityService } from '../UtilityService.js';
|
import { UtilityService } from '@/core/UtilityService.js';
|
||||||
|
import { RoleService } from '@/core/RoleService.js';
|
||||||
|
import { MiUser } from '@/models/User.js';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class InstanceEntityService {
|
export class InstanceEntityService {
|
||||||
constructor(
|
constructor(
|
||||||
private metaService: MetaService,
|
private metaService: MetaService,
|
||||||
|
private roleService: RoleService,
|
||||||
|
|
||||||
private utilityService: UtilityService,
|
private utilityService: UtilityService,
|
||||||
) {
|
) {
|
||||||
|
@ -22,8 +25,11 @@ export class InstanceEntityService {
|
||||||
@bindThis
|
@bindThis
|
||||||
public async pack(
|
public async pack(
|
||||||
instance: MiInstance,
|
instance: MiInstance,
|
||||||
|
me?: { id: MiUser['id']; } | null | undefined,
|
||||||
): Promise<Packed<'FederationInstance'>> {
|
): Promise<Packed<'FederationInstance'>> {
|
||||||
const meta = await this.metaService.fetch();
|
const meta = await this.metaService.fetch();
|
||||||
|
const iAmModerator = me ? await this.roleService.isModerator(me as MiUser) : false;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id: instance.id,
|
id: instance.id,
|
||||||
firstRetrievedAt: instance.firstRetrievedAt.toISOString(),
|
firstRetrievedAt: instance.firstRetrievedAt.toISOString(),
|
||||||
|
@ -48,6 +54,7 @@ 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,
|
||||||
|
moderationNote: iAmModerator ? instance.moderationNote : null,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -144,4 +144,9 @@ export class MiInstance {
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
public infoUpdatedAt: Date | null;
|
public infoUpdatedAt: Date | null;
|
||||||
|
|
||||||
|
@Column('varchar', {
|
||||||
|
length: 16384, default: '',
|
||||||
|
})
|
||||||
|
public moderationNote: string;
|
||||||
}
|
}
|
||||||
|
|
|
@ -107,5 +107,9 @@ export const packedFederationInstanceSchema = {
|
||||||
optional: false, nullable: true,
|
optional: false, nullable: true,
|
||||||
format: 'date-time',
|
format: 'date-time',
|
||||||
},
|
},
|
||||||
|
moderationNote: {
|
||||||
|
type: 'string',
|
||||||
|
optional: true, nullable: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
} as const;
|
} as const;
|
||||||
|
|
|
@ -24,8 +24,9 @@ export const paramDef = {
|
||||||
properties: {
|
properties: {
|
||||||
host: { type: 'string' },
|
host: { type: 'string' },
|
||||||
isSuspended: { type: 'boolean' },
|
isSuspended: { type: 'boolean' },
|
||||||
|
moderationNote: { type: 'string' },
|
||||||
},
|
},
|
||||||
required: ['host', 'isSuspended'],
|
required: ['host'],
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
|
@ -47,9 +48,10 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
||||||
|
|
||||||
await this.federatedInstanceService.update(instance.id, {
|
await this.federatedInstanceService.update(instance.id, {
|
||||||
isSuspended: ps.isSuspended,
|
isSuspended: ps.isSuspended,
|
||||||
|
moderationNote: ps.moderationNote,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (instance.isSuspended !== ps.isSuspended) {
|
if (ps.isSuspended != null && instance.isSuspended !== ps.isSuspended) {
|
||||||
if (ps.isSuspended) {
|
if (ps.isSuspended) {
|
||||||
this.moderationLogService.log(me, 'suspendRemoteInstance', {
|
this.moderationLogService.log(me, 'suspendRemoteInstance', {
|
||||||
id: instance.id,
|
id: instance.id,
|
||||||
|
@ -62,6 +64,15 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ps.moderationNote != null && instance.moderationNote !== ps.moderationNote) {
|
||||||
|
this.moderationLogService.log(me, 'updateRemoteInstanceNote', {
|
||||||
|
id: instance.id,
|
||||||
|
host: instance.host,
|
||||||
|
before: instance.moderationNote,
|
||||||
|
after: ps.moderationNote,
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,7 +43,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
||||||
const instance = await this.instancesRepository
|
const instance = await this.instancesRepository
|
||||||
.findOneBy({ host: this.utilityService.toPuny(ps.host) });
|
.findOneBy({ host: this.utilityService.toPuny(ps.host) });
|
||||||
|
|
||||||
return instance ? await this.instanceEntityService.pack(instance) : null;
|
return instance ? await this.instanceEntityService.pack(instance, me) : null;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,6 +69,7 @@ export const moderationLogTypes = [
|
||||||
'resetPassword',
|
'resetPassword',
|
||||||
'suspendRemoteInstance',
|
'suspendRemoteInstance',
|
||||||
'unsuspendRemoteInstance',
|
'unsuspendRemoteInstance',
|
||||||
|
'updateRemoteInstanceNote',
|
||||||
'markSensitiveDriveFile',
|
'markSensitiveDriveFile',
|
||||||
'unmarkSensitiveDriveFile',
|
'unmarkSensitiveDriveFile',
|
||||||
'resolveAbuseReport',
|
'resolveAbuseReport',
|
||||||
|
@ -209,6 +210,12 @@ export type ModerationLogPayloads = {
|
||||||
id: string;
|
id: string;
|
||||||
host: string;
|
host: string;
|
||||||
};
|
};
|
||||||
|
updateRemoteInstanceNote: {
|
||||||
|
id: string;
|
||||||
|
host: string;
|
||||||
|
before: string | null;
|
||||||
|
after: string | null;
|
||||||
|
};
|
||||||
markSensitiveDriveFile: {
|
markSensitiveDriveFile: {
|
||||||
fileId: string;
|
fileId: string;
|
||||||
fileUserId: string | null;
|
fileUserId: string | null;
|
||||||
|
|
|
@ -110,6 +110,12 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<CodeDiff :context="5" :hideHeader="true" :oldString="JSON5.stringify(log.info.before, null, '\t')" :newString="JSON5.stringify(log.info.after, null, '\t')" language="javascript" maxHeight="300px"/>
|
<CodeDiff :context="5" :hideHeader="true" :oldString="JSON5.stringify(log.info.before, null, '\t')" :newString="JSON5.stringify(log.info.after, null, '\t')" language="javascript" maxHeight="300px"/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
<template v-else-if="log.type === 'updateRemoteInstanceNote'">
|
||||||
|
<div>{{ i18n.ts.user }}: {{ log.info.userId }}</div>
|
||||||
|
<div :class="$style.diff">
|
||||||
|
<CodeDiff :context="5" :hideHeader="true" :oldString="log.info.before ?? ''" :newString="log.info.after ?? ''" maxHeight="300px"/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary>raw</summary>
|
<summary>raw</summary>
|
||||||
|
|
|
@ -39,6 +39,9 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<MkSwitch v-model="isBlocked" :disabled="!meta || !instance" @update:modelValue="toggleBlock">{{ i18n.ts.blockThisInstance }}</MkSwitch>
|
<MkSwitch v-model="isBlocked" :disabled="!meta || !instance" @update:modelValue="toggleBlock">{{ i18n.ts.blockThisInstance }}</MkSwitch>
|
||||||
<MkSwitch v-model="isSilenced" :disabled="!meta || !instance" @update:modelValue="toggleSilenced">{{ i18n.ts.silenceThisInstance }}</MkSwitch>
|
<MkSwitch v-model="isSilenced" :disabled="!meta || !instance" @update:modelValue="toggleSilenced">{{ i18n.ts.silenceThisInstance }}</MkSwitch>
|
||||||
<MkButton @click="refreshMetadata"><i class="ti ti-refresh"></i> Refresh metadata</MkButton>
|
<MkButton @click="refreshMetadata"><i class="ti ti-refresh"></i> Refresh metadata</MkButton>
|
||||||
|
<MkTextarea v-model="moderationNote" manualSave>
|
||||||
|
<template #label>{{ i18n.ts.moderationNote }}</template>
|
||||||
|
</MkTextarea>
|
||||||
</div>
|
</div>
|
||||||
</FormSection>
|
</FormSection>
|
||||||
|
|
||||||
|
@ -119,7 +122,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref, computed } from 'vue';
|
import { ref, computed, watch } from 'vue';
|
||||||
import * as Misskey from 'misskey-js';
|
import * as Misskey from 'misskey-js';
|
||||||
import MkChart from '@/components/MkChart.vue';
|
import MkChart from '@/components/MkChart.vue';
|
||||||
import MkObjectView from '@/components/MkObjectView.vue';
|
import MkObjectView from '@/components/MkObjectView.vue';
|
||||||
|
@ -141,6 +144,7 @@ import MkPagination from '@/components/MkPagination.vue';
|
||||||
import MkHorizontalSwipe from '@/components/MkHorizontalSwipe.vue';
|
import MkHorizontalSwipe from '@/components/MkHorizontalSwipe.vue';
|
||||||
import { getProxiedImageUrlNullable } from '@/scripts/media-proxy.js';
|
import { getProxiedImageUrlNullable } from '@/scripts/media-proxy.js';
|
||||||
import { dateString } from '@/filters/date.js';
|
import { dateString } from '@/filters/date.js';
|
||||||
|
import MkTextarea from '@/components/MkTextarea.vue';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
host: string;
|
host: string;
|
||||||
|
@ -155,6 +159,7 @@ const suspended = ref(false);
|
||||||
const isBlocked = ref(false);
|
const isBlocked = ref(false);
|
||||||
const isSilenced = ref(false);
|
const isSilenced = ref(false);
|
||||||
const faviconUrl = ref<string | null>(null);
|
const faviconUrl = ref<string | null>(null);
|
||||||
|
const moderationNote = ref('');
|
||||||
|
|
||||||
const usersPagination = {
|
const usersPagination = {
|
||||||
endpoint: iAmModerator ? 'admin/show-users' : 'users' as const,
|
endpoint: iAmModerator ? 'admin/show-users' : 'users' as const,
|
||||||
|
@ -167,6 +172,10 @@ const usersPagination = {
|
||||||
offsetMode: true,
|
offsetMode: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
watch(moderationNote, async () => {
|
||||||
|
await misskeyApi('admin/federation/update-instance', { host: instance.value.host, moderationNote: moderationNote.value });
|
||||||
|
});
|
||||||
|
|
||||||
async function fetch(): Promise<void> {
|
async function fetch(): Promise<void> {
|
||||||
if (iAmAdmin) {
|
if (iAmAdmin) {
|
||||||
meta.value = await misskeyApi('admin/meta');
|
meta.value = await misskeyApi('admin/meta');
|
||||||
|
@ -178,6 +187,7 @@ async function fetch(): Promise<void> {
|
||||||
isBlocked.value = instance.value?.isBlocked ?? false;
|
isBlocked.value = instance.value?.isBlocked ?? false;
|
||||||
isSilenced.value = instance.value?.isSilenced ?? false;
|
isSilenced.value = instance.value?.isSilenced ?? false;
|
||||||
faviconUrl.value = getProxiedImageUrlNullable(instance.value?.faviconUrl, 'preview') ?? getProxiedImageUrlNullable(instance.value?.iconUrl, 'preview');
|
faviconUrl.value = getProxiedImageUrlNullable(instance.value?.faviconUrl, 'preview') ?? getProxiedImageUrlNullable(instance.value?.iconUrl, 'preview');
|
||||||
|
moderationNote.value = instance.value?.moderationNote;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function toggleBlock(): Promise<void> {
|
async function toggleBlock(): Promise<void> {
|
||||||
|
|
|
@ -2316,6 +2316,9 @@ type ModerationLog = {
|
||||||
} | {
|
} | {
|
||||||
type: 'unsuspendRemoteInstance';
|
type: 'unsuspendRemoteInstance';
|
||||||
info: ModerationLogPayloads['unsuspendRemoteInstance'];
|
info: ModerationLogPayloads['unsuspendRemoteInstance'];
|
||||||
|
} | {
|
||||||
|
type: 'updateRemoteInstanceNote';
|
||||||
|
info: ModerationLogPayloads['updateRemoteInstanceNote'];
|
||||||
} | {
|
} | {
|
||||||
type: 'markSensitiveDriveFile';
|
type: 'markSensitiveDriveFile';
|
||||||
info: ModerationLogPayloads['markSensitiveDriveFile'];
|
info: ModerationLogPayloads['markSensitiveDriveFile'];
|
||||||
|
@ -2355,7 +2358,7 @@ type ModerationLog = {
|
||||||
});
|
});
|
||||||
|
|
||||||
// @public (undocumented)
|
// @public (undocumented)
|
||||||
export const moderationLogTypes: readonly ["updateServerSettings", "suspend", "unsuspend", "updateUserNote", "addCustomEmoji", "updateCustomEmoji", "deleteCustomEmoji", "assignRole", "unassignRole", "createRole", "updateRole", "deleteRole", "clearQueue", "promoteQueue", "deleteDriveFile", "deleteNote", "createGlobalAnnouncement", "createUserAnnouncement", "updateGlobalAnnouncement", "updateUserAnnouncement", "deleteGlobalAnnouncement", "deleteUserAnnouncement", "resetPassword", "suspendRemoteInstance", "unsuspendRemoteInstance", "markSensitiveDriveFile", "unmarkSensitiveDriveFile", "resolveAbuseReport", "createInvitation", "createAd", "updateAd", "deleteAd", "createAvatarDecoration", "updateAvatarDecoration", "deleteAvatarDecoration", "unsetUserAvatar", "unsetUserBanner"];
|
export const moderationLogTypes: readonly ["updateServerSettings", "suspend", "unsuspend", "updateUserNote", "addCustomEmoji", "updateCustomEmoji", "deleteCustomEmoji", "assignRole", "unassignRole", "createRole", "updateRole", "deleteRole", "clearQueue", "promoteQueue", "deleteDriveFile", "deleteNote", "createGlobalAnnouncement", "createUserAnnouncement", "updateGlobalAnnouncement", "updateUserAnnouncement", "deleteGlobalAnnouncement", "deleteUserAnnouncement", "resetPassword", "suspendRemoteInstance", "unsuspendRemoteInstance", "updateRemoteInstanceNote", "markSensitiveDriveFile", "unmarkSensitiveDriveFile", "resolveAbuseReport", "createInvitation", "createAd", "updateAd", "deleteAd", "createAvatarDecoration", "updateAvatarDecoration", "deleteAvatarDecoration", "unsetUserAvatar", "unsetUserBanner"];
|
||||||
|
|
||||||
// @public (undocumented)
|
// @public (undocumented)
|
||||||
type MuteCreateRequest = operations['mute/create']['requestBody']['content']['application/json'];
|
type MuteCreateRequest = operations['mute/create']['requestBody']['content']['application/json'];
|
||||||
|
|
|
@ -4480,6 +4480,7 @@ export type components = {
|
||||||
infoUpdatedAt: string | null;
|
infoUpdatedAt: string | null;
|
||||||
/** Format: date-time */
|
/** Format: date-time */
|
||||||
latestRequestReceivedAt: string | null;
|
latestRequestReceivedAt: string | null;
|
||||||
|
moderationNote?: string | null;
|
||||||
};
|
};
|
||||||
GalleryPost: {
|
GalleryPost: {
|
||||||
/**
|
/**
|
||||||
|
@ -7213,7 +7214,8 @@ export type operations = {
|
||||||
content: {
|
content: {
|
||||||
'application/json': {
|
'application/json': {
|
||||||
host: string;
|
host: string;
|
||||||
isSuspended: boolean;
|
isSuspended?: boolean;
|
||||||
|
moderationNote?: string;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -121,6 +121,7 @@ export const moderationLogTypes = [
|
||||||
'resetPassword',
|
'resetPassword',
|
||||||
'suspendRemoteInstance',
|
'suspendRemoteInstance',
|
||||||
'unsuspendRemoteInstance',
|
'unsuspendRemoteInstance',
|
||||||
|
'updateRemoteInstanceNote',
|
||||||
'markSensitiveDriveFile',
|
'markSensitiveDriveFile',
|
||||||
'unmarkSensitiveDriveFile',
|
'unmarkSensitiveDriveFile',
|
||||||
'resolveAbuseReport',
|
'resolveAbuseReport',
|
||||||
|
@ -261,6 +262,12 @@ export type ModerationLogPayloads = {
|
||||||
id: string;
|
id: string;
|
||||||
host: string;
|
host: string;
|
||||||
};
|
};
|
||||||
|
updateRemoteInstanceNote: {
|
||||||
|
id: string;
|
||||||
|
host: string;
|
||||||
|
before: string | null;
|
||||||
|
after: string | null;
|
||||||
|
};
|
||||||
markSensitiveDriveFile: {
|
markSensitiveDriveFile: {
|
||||||
fileId: string;
|
fileId: string;
|
||||||
fileUserId: string | null;
|
fileUserId: string | null;
|
||||||
|
|
|
@ -95,6 +95,9 @@ export type ModerationLog = {
|
||||||
} | {
|
} | {
|
||||||
type: 'unsuspendRemoteInstance';
|
type: 'unsuspendRemoteInstance';
|
||||||
info: ModerationLogPayloads['unsuspendRemoteInstance'];
|
info: ModerationLogPayloads['unsuspendRemoteInstance'];
|
||||||
|
} | {
|
||||||
|
type: 'updateRemoteInstanceNote';
|
||||||
|
info: ModerationLogPayloads['updateRemoteInstanceNote'];
|
||||||
} | {
|
} | {
|
||||||
type: 'markSensitiveDriveFile';
|
type: 'markSensitiveDriveFile';
|
||||||
info: ModerationLogPayloads['markSensitiveDriveFile'];
|
info: ModerationLogPayloads['markSensitiveDriveFile'];
|
||||||
|
|
Loading…
Reference in New Issue