mirror of
https://codeberg.org/yeentown/barkey.git
synced 2025-04-28 17:46:56 +00:00
View MR for information: https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/925 Closes #911 and #969 Approved-by: dakkar <dakkar@thenautilus.net> Approved-by: Marie <github@yuugi.dev>
This commit is contained in:
commit
141bce2be7
33 changed files with 694 additions and 59 deletions
80
locales/index.d.ts
vendored
80
locales/index.d.ts
vendored
|
@ -1403,7 +1403,7 @@ export interface Locale extends ILocale {
|
||||||
*/
|
*/
|
||||||
"inputNewFileName": string;
|
"inputNewFileName": string;
|
||||||
/**
|
/**
|
||||||
* 新しいキャプションを入力してください
|
* Enter new alt text
|
||||||
*/
|
*/
|
||||||
"inputNewDescription": string;
|
"inputNewDescription": string;
|
||||||
/**
|
/**
|
||||||
|
@ -2603,11 +2603,11 @@ export interface Locale extends ILocale {
|
||||||
*/
|
*/
|
||||||
"description": string;
|
"description": string;
|
||||||
/**
|
/**
|
||||||
* キャプションを付ける
|
* Add alt text
|
||||||
*/
|
*/
|
||||||
"describeFile": string;
|
"describeFile": string;
|
||||||
/**
|
/**
|
||||||
* キャプションを入力
|
* Enter alt text
|
||||||
*/
|
*/
|
||||||
"enterFileDescription": string;
|
"enterFileDescription": string;
|
||||||
/**
|
/**
|
||||||
|
@ -4084,7 +4084,7 @@ export interface Locale extends ILocale {
|
||||||
*/
|
*/
|
||||||
"windowRestore": string;
|
"windowRestore": string;
|
||||||
/**
|
/**
|
||||||
* キャプション
|
* Alt text
|
||||||
*/
|
*/
|
||||||
"caption": string;
|
"caption": string;
|
||||||
/**
|
/**
|
||||||
|
@ -10254,6 +10254,66 @@ export interface Locale extends ILocale {
|
||||||
* Allowed quote posts from user
|
* Allowed quote posts from user
|
||||||
*/
|
*/
|
||||||
"allowQuotesUser": string;
|
"allowQuotesUser": string;
|
||||||
|
/**
|
||||||
|
* Cleared a user's drive files
|
||||||
|
*/
|
||||||
|
"clearUserFiles": string;
|
||||||
|
/**
|
||||||
|
* Marked user as NSFW
|
||||||
|
*/
|
||||||
|
"nsfwUser": string;
|
||||||
|
/**
|
||||||
|
* Un-marked user as NSFW
|
||||||
|
*/
|
||||||
|
"unNsfwUser": string;
|
||||||
|
/**
|
||||||
|
* Silenced user
|
||||||
|
*/
|
||||||
|
"silenceUser": string;
|
||||||
|
/**
|
||||||
|
* Un-silenced user
|
||||||
|
*/
|
||||||
|
"unSilenceUser": string;
|
||||||
|
/**
|
||||||
|
* Created an account
|
||||||
|
*/
|
||||||
|
"createAccount": string;
|
||||||
|
/**
|
||||||
|
* Cleared remote drive files
|
||||||
|
*/
|
||||||
|
"clearRemoteFiles": string;
|
||||||
|
/**
|
||||||
|
* Cleared owner-less drive files
|
||||||
|
*/
|
||||||
|
"clearOwnerlessFiles": string;
|
||||||
|
/**
|
||||||
|
* Updated custom emojis
|
||||||
|
*/
|
||||||
|
"updateCustomEmojis": string;
|
||||||
|
/**
|
||||||
|
* Imported custom emojis
|
||||||
|
*/
|
||||||
|
"importCustomEmojis": string;
|
||||||
|
/**
|
||||||
|
* Cleared an instance's drive files
|
||||||
|
*/
|
||||||
|
"clearInstanceFiles": string;
|
||||||
|
/**
|
||||||
|
* Severed follow relations with an instance
|
||||||
|
*/
|
||||||
|
"severFollowRelations": string;
|
||||||
|
/**
|
||||||
|
* Created a note promo
|
||||||
|
*/
|
||||||
|
"createPromo": string;
|
||||||
|
/**
|
||||||
|
* Added a relay
|
||||||
|
*/
|
||||||
|
"addRelay": string;
|
||||||
|
/**
|
||||||
|
* Removed a relay
|
||||||
|
*/
|
||||||
|
"removeRelay": string;
|
||||||
};
|
};
|
||||||
"_fileViewer": {
|
"_fileViewer": {
|
||||||
/**
|
/**
|
||||||
|
@ -11601,6 +11661,18 @@ export interface Locale extends ILocale {
|
||||||
* Flash
|
* Flash
|
||||||
*/
|
*/
|
||||||
"flash": string;
|
"flash": string;
|
||||||
|
/**
|
||||||
|
* Files removed
|
||||||
|
*/
|
||||||
|
"filesRemoved": string;
|
||||||
|
/**
|
||||||
|
* File imported
|
||||||
|
*/
|
||||||
|
"fileImported": string;
|
||||||
|
/**
|
||||||
|
* Failed to load note
|
||||||
|
*/
|
||||||
|
"cannotLoadNote": string;
|
||||||
"_flash": {
|
"_flash": {
|
||||||
/**
|
/**
|
||||||
* Flash Content Hidden
|
* Flash Content Hidden
|
||||||
|
|
|
@ -162,7 +162,6 @@ export class NoteDeleteService {
|
||||||
noteUserId: note.userId,
|
noteUserId: note.userId,
|
||||||
noteUserUsername: user.username,
|
noteUserUsername: user.username,
|
||||||
noteUserHost: user.host,
|
noteUserHost: user.host,
|
||||||
note: note,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@ import type { Config } from '@/config.js';
|
||||||
import { ApiError } from '@/server/api/error.js';
|
import { ApiError } from '@/server/api/error.js';
|
||||||
import { Packed } from '@/misc/json-schema.js';
|
import { Packed } from '@/misc/json-schema.js';
|
||||||
import { RoleService } from '@/core/RoleService.js';
|
import { RoleService } from '@/core/RoleService.js';
|
||||||
|
import { ModerationLogService } from '@/core/ModerationLogService.js';
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
tags: ['admin'],
|
tags: ['admin'],
|
||||||
|
@ -96,6 +97,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
||||||
private userEntityService: UserEntityService,
|
private userEntityService: UserEntityService,
|
||||||
private signupService: SignupService,
|
private signupService: SignupService,
|
||||||
private instanceActorService: InstanceActorService,
|
private instanceActorService: InstanceActorService,
|
||||||
|
private readonly moderationLogService: ModerationLogService,
|
||||||
) {
|
) {
|
||||||
super(meta, paramDef, async (ps, _me, token) => {
|
super(meta, paramDef, async (ps, _me, token) => {
|
||||||
const me = _me ? await this.usersRepository.findOneByOrFail({ id: _me.id }) : null;
|
const me = _me ? await this.usersRepository.findOneByOrFail({ id: _me.id }) : null;
|
||||||
|
@ -137,6 +139,13 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
||||||
approved: true,
|
approved: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (me) {
|
||||||
|
await this.moderationLogService.log(me, 'createAccount', {
|
||||||
|
userId: account.id,
|
||||||
|
userUsername: account.username,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const res = await this.userEntityService.pack(account, account, {
|
const res = await this.userEntityService.pack(account, account, {
|
||||||
schema: 'MeDetailed',
|
schema: 'MeDetailed',
|
||||||
includeSecrets: true,
|
includeSecrets: true,
|
||||||
|
|
|
@ -8,6 +8,8 @@ import { Endpoint } from '@/server/api/endpoint-base.js';
|
||||||
import type { DriveFilesRepository } from '@/models/_.js';
|
import type { DriveFilesRepository } from '@/models/_.js';
|
||||||
import { DriveService } from '@/core/DriveService.js';
|
import { DriveService } from '@/core/DriveService.js';
|
||||||
import { DI } from '@/di-symbols.js';
|
import { DI } from '@/di-symbols.js';
|
||||||
|
import { ModerationLogService } from '@/core/ModerationLogService.js';
|
||||||
|
import { CacheService } from '@/core/CacheService.js';
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
tags: ['admin'],
|
tags: ['admin'],
|
||||||
|
@ -30,14 +32,23 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
||||||
constructor(
|
constructor(
|
||||||
@Inject(DI.driveFilesRepository)
|
@Inject(DI.driveFilesRepository)
|
||||||
private driveFilesRepository: DriveFilesRepository,
|
private driveFilesRepository: DriveFilesRepository,
|
||||||
|
private readonly cacheService: CacheService,
|
||||||
|
private readonly moderationLogService: ModerationLogService,
|
||||||
private driveService: DriveService,
|
private driveService: DriveService,
|
||||||
) {
|
) {
|
||||||
super(meta, paramDef, async (ps, me) => {
|
super(meta, paramDef, async (ps, me) => {
|
||||||
|
const user = await this.cacheService.findUserById(ps.userId);
|
||||||
const files = await this.driveFilesRepository.findBy({
|
const files = await this.driveFilesRepository.findBy({
|
||||||
userId: ps.userId,
|
userId: ps.userId,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
await this.moderationLogService.log(me, 'clearUserFiles', {
|
||||||
|
userId: ps.userId,
|
||||||
|
userUsername: user.username,
|
||||||
|
userHost: user.host,
|
||||||
|
count: files.length,
|
||||||
|
});
|
||||||
|
|
||||||
for (const file of files) {
|
for (const file of files) {
|
||||||
this.driveService.deleteFile(file, false, me);
|
this.driveService.deleteFile(file, false, me);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
import { Endpoint } from '@/server/api/endpoint-base.js';
|
import { Endpoint } from '@/server/api/endpoint-base.js';
|
||||||
import { QueueService } from '@/core/QueueService.js';
|
import { QueueService } from '@/core/QueueService.js';
|
||||||
|
import { ModerationLogService } from '@/core/ModerationLogService.js';
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
tags: ['admin'],
|
tags: ['admin'],
|
||||||
|
@ -25,9 +26,11 @@ export const paramDef = {
|
||||||
export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-disable-line import/no-default-export
|
export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-disable-line import/no-default-export
|
||||||
constructor(
|
constructor(
|
||||||
private queueService: QueueService,
|
private queueService: QueueService,
|
||||||
|
private readonly moderationLogService: ModerationLogService,
|
||||||
) {
|
) {
|
||||||
super(meta, paramDef, async (ps, me) => {
|
super(meta, paramDef, async (ps, me) => {
|
||||||
this.queueService.createCleanRemoteFilesJob();
|
await this.moderationLogService.log(me, 'clearRemoteFiles', {});
|
||||||
|
await this.queueService.createCleanRemoteFilesJob();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ import { Endpoint } from '@/server/api/endpoint-base.js';
|
||||||
import type { DriveFilesRepository } from '@/models/_.js';
|
import type { DriveFilesRepository } from '@/models/_.js';
|
||||||
import { DriveService } from '@/core/DriveService.js';
|
import { DriveService } from '@/core/DriveService.js';
|
||||||
import { DI } from '@/di-symbols.js';
|
import { DI } from '@/di-symbols.js';
|
||||||
|
import { ModerationLogService } from '@/core/ModerationLogService.js';
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
tags: ['admin'],
|
tags: ['admin'],
|
||||||
|
@ -29,7 +30,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
||||||
constructor(
|
constructor(
|
||||||
@Inject(DI.driveFilesRepository)
|
@Inject(DI.driveFilesRepository)
|
||||||
private driveFilesRepository: DriveFilesRepository,
|
private driveFilesRepository: DriveFilesRepository,
|
||||||
|
private readonly moderationLogService: ModerationLogService,
|
||||||
private driveService: DriveService,
|
private driveService: DriveService,
|
||||||
) {
|
) {
|
||||||
super(meta, paramDef, async (ps, me) => {
|
super(meta, paramDef, async (ps, me) => {
|
||||||
|
@ -37,6 +38,10 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
||||||
userId: IsNull(),
|
userId: IsNull(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
await this.moderationLogService.log(me, 'clearOwnerlessFiles', {
|
||||||
|
count: files.length,
|
||||||
|
});
|
||||||
|
|
||||||
for (const file of files) {
|
for (const file of files) {
|
||||||
this.driveService.deleteFile(file);
|
this.driveService.deleteFile(file);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
import { Endpoint } from '@/server/api/endpoint-base.js';
|
import { Endpoint } from '@/server/api/endpoint-base.js';
|
||||||
import { CustomEmojiService } from '@/core/CustomEmojiService.js';
|
import { CustomEmojiService } from '@/core/CustomEmojiService.js';
|
||||||
|
import { ModerationLogService } from '@/core/ModerationLogService.js';
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
tags: ['admin'],
|
tags: ['admin'],
|
||||||
|
@ -32,8 +33,13 @@ export const paramDef = {
|
||||||
export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-disable-line import/no-default-export
|
export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-disable-line import/no-default-export
|
||||||
constructor(
|
constructor(
|
||||||
private customEmojiService: CustomEmojiService,
|
private customEmojiService: CustomEmojiService,
|
||||||
|
private readonly moderationLogService: ModerationLogService,
|
||||||
) {
|
) {
|
||||||
super(meta, paramDef, async (ps, me) => {
|
super(meta, paramDef, async (ps, me) => {
|
||||||
|
await this.moderationLogService.log(me, 'updateCustomEmojis', {
|
||||||
|
ids: ps.ids,
|
||||||
|
addAliases: ps.aliases,
|
||||||
|
});
|
||||||
await this.customEmojiService.addAliasesBulk(ps.ids, ps.aliases.map(a => a.normalize('NFC')));
|
await this.customEmojiService.addAliasesBulk(ps.ids, ps.aliases.map(a => a.normalize('NFC')));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,9 +3,12 @@
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Injectable } from '@nestjs/common';
|
import { Inject, Injectable } from '@nestjs/common';
|
||||||
import { Endpoint } from '@/server/api/endpoint-base.js';
|
import { Endpoint } from '@/server/api/endpoint-base.js';
|
||||||
import { QueueService } from '@/core/QueueService.js';
|
import { QueueService } from '@/core/QueueService.js';
|
||||||
|
import { ModerationLogService } from '@/core/ModerationLogService.js';
|
||||||
|
import type { DriveFilesRepository } from '@/models/_.js';
|
||||||
|
import { DI } from '@/di-symbols.js';
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
secure: true,
|
secure: true,
|
||||||
|
@ -25,9 +28,16 @@ export const paramDef = {
|
||||||
export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-disable-line import/no-default-export
|
export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-disable-line import/no-default-export
|
||||||
constructor(
|
constructor(
|
||||||
private queueService: QueueService,
|
private queueService: QueueService,
|
||||||
|
private readonly moderationLogService: ModerationLogService,
|
||||||
|
@Inject(DI.driveFilesRepository)
|
||||||
|
private readonly driveFilesRepository: DriveFilesRepository,
|
||||||
) {
|
) {
|
||||||
super(meta, paramDef, async (ps, me) => {
|
super(meta, paramDef, async (ps, me) => {
|
||||||
this.queueService.createImportCustomEmojisJob(me, ps.fileId);
|
const file = await driveFilesRepository.findOneByOrFail({ id: ps.fileId });
|
||||||
|
await this.moderationLogService.log(me, 'importCustomEmojis', {
|
||||||
|
fileName: file.name,
|
||||||
|
});
|
||||||
|
await this.queueService.createImportCustomEmojisJob(me, ps.fileId);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
import { Endpoint } from '@/server/api/endpoint-base.js';
|
import { Endpoint } from '@/server/api/endpoint-base.js';
|
||||||
import { CustomEmojiService } from '@/core/CustomEmojiService.js';
|
import { CustomEmojiService } from '@/core/CustomEmojiService.js';
|
||||||
|
import { ModerationLogService } from '@/core/ModerationLogService.js';
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
tags: ['admin'],
|
tags: ['admin'],
|
||||||
|
@ -32,8 +33,13 @@ export const paramDef = {
|
||||||
export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-disable-line import/no-default-export
|
export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-disable-line import/no-default-export
|
||||||
constructor(
|
constructor(
|
||||||
private customEmojiService: CustomEmojiService,
|
private customEmojiService: CustomEmojiService,
|
||||||
|
private readonly moderationLogService: ModerationLogService,
|
||||||
) {
|
) {
|
||||||
super(meta, paramDef, async (ps, me) => {
|
super(meta, paramDef, async (ps, me) => {
|
||||||
|
await this.moderationLogService.log(me, 'updateCustomEmojis', {
|
||||||
|
ids: ps.ids,
|
||||||
|
delAliases: ps.aliases,
|
||||||
|
});
|
||||||
await this.customEmojiService.removeAliasesBulk(ps.ids, ps.aliases.map(a => a.normalize('NFC')));
|
await this.customEmojiService.removeAliasesBulk(ps.ids, ps.aliases.map(a => a.normalize('NFC')));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
import { Endpoint } from '@/server/api/endpoint-base.js';
|
import { Endpoint } from '@/server/api/endpoint-base.js';
|
||||||
import { CustomEmojiService } from '@/core/CustomEmojiService.js';
|
import { CustomEmojiService } from '@/core/CustomEmojiService.js';
|
||||||
|
import { ModerationLogService } from '@/core/ModerationLogService.js';
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
tags: ['admin'],
|
tags: ['admin'],
|
||||||
|
@ -32,8 +33,13 @@ export const paramDef = {
|
||||||
export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-disable-line import/no-default-export
|
export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-disable-line import/no-default-export
|
||||||
constructor(
|
constructor(
|
||||||
private customEmojiService: CustomEmojiService,
|
private customEmojiService: CustomEmojiService,
|
||||||
|
private readonly moderationLogService: ModerationLogService,
|
||||||
) {
|
) {
|
||||||
super(meta, paramDef, async (ps, me) => {
|
super(meta, paramDef, async (ps, me) => {
|
||||||
|
await this.moderationLogService.log(me, 'updateCustomEmojis', {
|
||||||
|
ids: ps.ids,
|
||||||
|
setAliases: ps.aliases,
|
||||||
|
});
|
||||||
await this.customEmojiService.setAliasesBulk(ps.ids, ps.aliases.map(a => a.normalize('NFC')));
|
await this.customEmojiService.setAliasesBulk(ps.ids, ps.aliases.map(a => a.normalize('NFC')));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
import { Endpoint } from '@/server/api/endpoint-base.js';
|
import { Endpoint } from '@/server/api/endpoint-base.js';
|
||||||
import { CustomEmojiService } from '@/core/CustomEmojiService.js';
|
import { CustomEmojiService } from '@/core/CustomEmojiService.js';
|
||||||
|
import { ModerationLogService } from '@/core/ModerationLogService.js';
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
tags: ['admin'],
|
tags: ['admin'],
|
||||||
|
@ -34,8 +35,13 @@ export const paramDef = {
|
||||||
export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-disable-line import/no-default-export
|
export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-disable-line import/no-default-export
|
||||||
constructor(
|
constructor(
|
||||||
private customEmojiService: CustomEmojiService,
|
private customEmojiService: CustomEmojiService,
|
||||||
|
private readonly moderationLogService: ModerationLogService,
|
||||||
) {
|
) {
|
||||||
super(meta, paramDef, async (ps, me) => {
|
super(meta, paramDef, async (ps, me) => {
|
||||||
|
await this.moderationLogService.log(me, 'updateCustomEmojis', {
|
||||||
|
ids: ps.ids,
|
||||||
|
category: ps.category,
|
||||||
|
});
|
||||||
await this.customEmojiService.setCategoryBulk(ps.ids, ps.category?.normalize('NFC') ?? null);
|
await this.customEmojiService.setCategoryBulk(ps.ids, ps.category?.normalize('NFC') ?? null);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
import { Endpoint } from '@/server/api/endpoint-base.js';
|
import { Endpoint } from '@/server/api/endpoint-base.js';
|
||||||
import { CustomEmojiService } from '@/core/CustomEmojiService.js';
|
import { CustomEmojiService } from '@/core/CustomEmojiService.js';
|
||||||
|
import { ModerationLogService } from '@/core/ModerationLogService.js';
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
tags: ['admin'],
|
tags: ['admin'],
|
||||||
|
@ -34,8 +35,13 @@ export const paramDef = {
|
||||||
export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-disable-line import/no-default-export
|
export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-disable-line import/no-default-export
|
||||||
constructor(
|
constructor(
|
||||||
private customEmojiService: CustomEmojiService,
|
private customEmojiService: CustomEmojiService,
|
||||||
|
private readonly moderationLogService: ModerationLogService,
|
||||||
) {
|
) {
|
||||||
super(meta, paramDef, async (ps, me) => {
|
super(meta, paramDef, async (ps, me) => {
|
||||||
|
await this.moderationLogService.log(me, 'updateCustomEmojis', {
|
||||||
|
ids: ps.ids,
|
||||||
|
license: ps.license,
|
||||||
|
});
|
||||||
await this.customEmojiService.setLicenseBulk(ps.ids, ps.license ?? null);
|
await this.customEmojiService.setLicenseBulk(ps.ids, ps.license ?? null);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ import { Endpoint } from '@/server/api/endpoint-base.js';
|
||||||
import type { DriveFilesRepository } from '@/models/_.js';
|
import type { DriveFilesRepository } from '@/models/_.js';
|
||||||
import { DriveService } from '@/core/DriveService.js';
|
import { DriveService } from '@/core/DriveService.js';
|
||||||
import { DI } from '@/di-symbols.js';
|
import { DI } from '@/di-symbols.js';
|
||||||
|
import { ModerationLogService } from '@/core/ModerationLogService.js';
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
tags: ['admin'],
|
tags: ['admin'],
|
||||||
|
@ -30,7 +31,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
||||||
constructor(
|
constructor(
|
||||||
@Inject(DI.driveFilesRepository)
|
@Inject(DI.driveFilesRepository)
|
||||||
private driveFilesRepository: DriveFilesRepository,
|
private driveFilesRepository: DriveFilesRepository,
|
||||||
|
private readonly moderationLogService: ModerationLogService,
|
||||||
private driveService: DriveService,
|
private driveService: DriveService,
|
||||||
) {
|
) {
|
||||||
super(meta, paramDef, async (ps, me) => {
|
super(meta, paramDef, async (ps, me) => {
|
||||||
|
@ -38,6 +39,11 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
||||||
userHost: ps.host,
|
userHost: ps.host,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
await this.moderationLogService.log(me, 'clearInstanceFiles', {
|
||||||
|
host: ps.host,
|
||||||
|
count: files.length,
|
||||||
|
});
|
||||||
|
|
||||||
for (const file of files) {
|
for (const file of files) {
|
||||||
this.driveService.deleteFile(file);
|
this.driveService.deleteFile(file);
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ import { Endpoint } from '@/server/api/endpoint-base.js';
|
||||||
import type { FollowingsRepository, UsersRepository } from '@/models/_.js';
|
import type { FollowingsRepository, UsersRepository } from '@/models/_.js';
|
||||||
import { DI } from '@/di-symbols.js';
|
import { DI } from '@/di-symbols.js';
|
||||||
import { QueueService } from '@/core/QueueService.js';
|
import { QueueService } from '@/core/QueueService.js';
|
||||||
|
import { ModerationLogService } from '@/core/ModerationLogService.js';
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
tags: ['admin'],
|
tags: ['admin'],
|
||||||
|
@ -35,6 +36,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
||||||
private followingsRepository: FollowingsRepository,
|
private followingsRepository: FollowingsRepository,
|
||||||
|
|
||||||
private queueService: QueueService,
|
private queueService: QueueService,
|
||||||
|
private readonly moderationLogService: ModerationLogService,
|
||||||
) {
|
) {
|
||||||
super(meta, paramDef, async (ps, me) => {
|
super(meta, paramDef, async (ps, me) => {
|
||||||
const followings = await this.followingsRepository.findBy([
|
const followings = await this.followingsRepository.findBy([
|
||||||
|
@ -51,6 +53,10 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
||||||
this.usersRepository.findOneByOrFail({ id: f.followeeId }),
|
this.usersRepository.findOneByOrFail({ id: f.followeeId }),
|
||||||
]).then(([from, to]) => [{ id: from.id }, { id: to.id }])));
|
]).then(([from, to]) => [{ id: from.id }, { id: to.id }])));
|
||||||
|
|
||||||
|
await this.moderationLogService.log(me, 'severFollowRelations', {
|
||||||
|
host: ps.host,
|
||||||
|
});
|
||||||
|
|
||||||
this.queueService.createUnfollowJob(pairs.map(p => ({ from: p[0], to: p[1], silent: true })));
|
this.queueService.createUnfollowJob(pairs.map(p => ({ from: p[0], to: p[1], silent: true })));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,9 +5,10 @@
|
||||||
|
|
||||||
import { Inject, Injectable } from '@nestjs/common';
|
import { Inject, Injectable } from '@nestjs/common';
|
||||||
import { Endpoint } from '@/server/api/endpoint-base.js';
|
import { Endpoint } from '@/server/api/endpoint-base.js';
|
||||||
import type { UsersRepository, UserProfilesRepository } from '@/models/_.js';
|
import type { UserProfilesRepository } from '@/models/_.js';
|
||||||
import { DI } from '@/di-symbols.js';
|
import { DI } from '@/di-symbols.js';
|
||||||
import { CacheService } from '@/core/CacheService.js';
|
import { CacheService } from '@/core/CacheService.js';
|
||||||
|
import { ModerationLogService } from '@/core/ModerationLogService.js';
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
tags: ['admin'],
|
tags: ['admin'],
|
||||||
|
@ -28,20 +29,19 @@ export const paramDef = {
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-disable-line import/no-default-export
|
export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-disable-line import/no-default-export
|
||||||
constructor(
|
constructor(
|
||||||
@Inject(DI.usersRepository)
|
|
||||||
private readonly usersRepository: UsersRepository,
|
|
||||||
|
|
||||||
@Inject(DI.userProfilesRepository)
|
@Inject(DI.userProfilesRepository)
|
||||||
private readonly userProfilesRepository: UserProfilesRepository,
|
private readonly userProfilesRepository: UserProfilesRepository,
|
||||||
|
private readonly moderationLogService: ModerationLogService,
|
||||||
private readonly cacheService: CacheService,
|
private readonly cacheService: CacheService,
|
||||||
) {
|
) {
|
||||||
super(meta, paramDef, async (ps, me) => {
|
super(meta, paramDef, async (ps, me) => {
|
||||||
const user = await this.usersRepository.findOneBy({ id: ps.userId });
|
const user = await this.cacheService.findUserById(ps.userId);
|
||||||
|
|
||||||
if (user == null) {
|
await this.moderationLogService.log(me, 'nsfwUser', {
|
||||||
throw new Error('user not found');
|
userId: ps.userId,
|
||||||
}
|
userUsername: user.username,
|
||||||
|
userHost: user.host,
|
||||||
|
});
|
||||||
|
|
||||||
await this.userProfilesRepository.update(user.id, {
|
await this.userProfilesRepository.update(user.id, {
|
||||||
alwaysMarkNsfw: true,
|
alwaysMarkNsfw: true,
|
||||||
|
|
|
@ -8,6 +8,8 @@ import { Endpoint } from '@/server/api/endpoint-base.js';
|
||||||
import type { PromoNotesRepository } from '@/models/_.js';
|
import type { PromoNotesRepository } from '@/models/_.js';
|
||||||
import { GetterService } from '@/server/api/GetterService.js';
|
import { GetterService } from '@/server/api/GetterService.js';
|
||||||
import { DI } from '@/di-symbols.js';
|
import { DI } from '@/di-symbols.js';
|
||||||
|
import { ModerationLogService } from '@/core/ModerationLogService.js';
|
||||||
|
import { CacheService } from '@/core/CacheService.js';
|
||||||
import { ApiError } from '../../../error.js';
|
import { ApiError } from '../../../error.js';
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
|
@ -46,7 +48,8 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
||||||
constructor(
|
constructor(
|
||||||
@Inject(DI.promoNotesRepository)
|
@Inject(DI.promoNotesRepository)
|
||||||
private promoNotesRepository: PromoNotesRepository,
|
private promoNotesRepository: PromoNotesRepository,
|
||||||
|
private readonly moderationLogService: ModerationLogService,
|
||||||
|
private readonly cacheService: CacheService,
|
||||||
private getterService: GetterService,
|
private getterService: GetterService,
|
||||||
) {
|
) {
|
||||||
super(meta, paramDef, async (ps, me) => {
|
super(meta, paramDef, async (ps, me) => {
|
||||||
|
@ -61,6 +64,14 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
||||||
throw new ApiError(meta.errors.alreadyPromoted);
|
throw new ApiError(meta.errors.alreadyPromoted);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const user = await this.cacheService.findUserById(note.userId);
|
||||||
|
await this.moderationLogService.log(me, 'createPromo', {
|
||||||
|
noteId: note.id,
|
||||||
|
noteUserId: user.id,
|
||||||
|
noteUserUsername: user.username,
|
||||||
|
noteUserHost: user.host,
|
||||||
|
});
|
||||||
|
|
||||||
await this.promoNotesRepository.insert({
|
await this.promoNotesRepository.insert({
|
||||||
noteId: note.id,
|
noteId: note.id,
|
||||||
expiresAt: new Date(ps.expiresAt),
|
expiresAt: new Date(ps.expiresAt),
|
||||||
|
|
|
@ -8,6 +8,7 @@ import { Injectable } from '@nestjs/common';
|
||||||
import { Endpoint } from '@/server/api/endpoint-base.js';
|
import { Endpoint } from '@/server/api/endpoint-base.js';
|
||||||
import { RelayService } from '@/core/RelayService.js';
|
import { RelayService } from '@/core/RelayService.js';
|
||||||
import { ApiError } from '../../../error.js';
|
import { ApiError } from '../../../error.js';
|
||||||
|
import { ModerationLogService } from '@/core/ModerationLogService.js';
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
tags: ['admin'],
|
tags: ['admin'],
|
||||||
|
@ -64,6 +65,7 @@ export const paramDef = {
|
||||||
export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-disable-line import/no-default-export
|
export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-disable-line import/no-default-export
|
||||||
constructor(
|
constructor(
|
||||||
private relayService: RelayService,
|
private relayService: RelayService,
|
||||||
|
private readonly moderationLogService: ModerationLogService,
|
||||||
) {
|
) {
|
||||||
super(meta, paramDef, async (ps, me) => {
|
super(meta, paramDef, async (ps, me) => {
|
||||||
try {
|
try {
|
||||||
|
@ -72,6 +74,10 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
||||||
throw new ApiError(meta.errors.invalidUrl);
|
throw new ApiError(meta.errors.invalidUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await this.moderationLogService.log(me, 'addRelay', {
|
||||||
|
inbox: ps.inbox,
|
||||||
|
});
|
||||||
|
|
||||||
return await this.relayService.addRelay(ps.inbox);
|
return await this.relayService.addRelay(ps.inbox);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
import { Endpoint } from '@/server/api/endpoint-base.js';
|
import { Endpoint } from '@/server/api/endpoint-base.js';
|
||||||
import { RelayService } from '@/core/RelayService.js';
|
import { RelayService } from '@/core/RelayService.js';
|
||||||
|
import { ModerationLogService } from '@/core/ModerationLogService.js';
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
tags: ['admin'],
|
tags: ['admin'],
|
||||||
|
@ -27,9 +28,13 @@ export const paramDef = {
|
||||||
export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-disable-line import/no-default-export
|
export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-disable-line import/no-default-export
|
||||||
constructor(
|
constructor(
|
||||||
private relayService: RelayService,
|
private relayService: RelayService,
|
||||||
|
private readonly moderationLogService: ModerationLogService,
|
||||||
) {
|
) {
|
||||||
super(meta, paramDef, async (ps, me) => {
|
super(meta, paramDef, async (ps, me) => {
|
||||||
return await this.relayService.removeRelay(ps.inbox);
|
await this.moderationLogService.log(me, 'removeRelay', {
|
||||||
|
inbox: ps.inbox,
|
||||||
|
});
|
||||||
|
await this.relayService.removeRelay(ps.inbox);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,9 @@ import { Endpoint } from '@/server/api/endpoint-base.js';
|
||||||
import type { UsersRepository } from '@/models/_.js';
|
import type { UsersRepository } from '@/models/_.js';
|
||||||
import { DI } from '@/di-symbols.js';
|
import { DI } from '@/di-symbols.js';
|
||||||
import { RoleService } from '@/core/RoleService.js';
|
import { RoleService } from '@/core/RoleService.js';
|
||||||
|
import { CacheService } from '@/core/CacheService.js';
|
||||||
|
import { ModerationLogService } from '@/core/ModerationLogService.js';
|
||||||
|
import { GlobalEventService } from '@/core/GlobalEventService.js';
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
tags: ['admin'],
|
tags: ['admin'],
|
||||||
|
@ -29,24 +32,32 @@ export const paramDef = {
|
||||||
export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-disable-line import/no-default-export
|
export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-disable-line import/no-default-export
|
||||||
constructor(
|
constructor(
|
||||||
@Inject(DI.usersRepository)
|
@Inject(DI.usersRepository)
|
||||||
private usersRepository: UsersRepository,
|
private readonly usersRepository: UsersRepository,
|
||||||
|
private readonly cacheService: CacheService,
|
||||||
private roleService: RoleService,
|
private readonly moderationLogService: ModerationLogService,
|
||||||
|
private readonly roleService: RoleService,
|
||||||
|
private readonly globalEventService: GlobalEventService,
|
||||||
) {
|
) {
|
||||||
super(meta, paramDef, async (ps, me) => {
|
super(meta, paramDef, async (ps, me) => {
|
||||||
const user = await this.usersRepository.findOneBy({ id: ps.userId });
|
const user = await this.cacheService.findUserById(ps.userId);
|
||||||
|
|
||||||
if (user == null) {
|
|
||||||
throw new Error('user not found');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (await this.roleService.isModerator(user)) {
|
if (await this.roleService.isModerator(user)) {
|
||||||
throw new Error('cannot silence moderator account');
|
throw new Error('cannot silence moderator account');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await this.moderationLogService.log(me, 'silenceUser', {
|
||||||
|
userId: ps.userId,
|
||||||
|
userUsername: user.username,
|
||||||
|
userHost: user.host,
|
||||||
|
});
|
||||||
|
|
||||||
await this.usersRepository.update(user.id, {
|
await this.usersRepository.update(user.id, {
|
||||||
isSilenced: true,
|
isSilenced: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.globalEventService.publishInternalEvent(user.host == null ? 'localUserUpdated' : 'remoteUserUpdated', {
|
||||||
|
id: user.id,
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,8 +5,10 @@
|
||||||
|
|
||||||
import { Inject, Injectable } from '@nestjs/common';
|
import { Inject, Injectable } from '@nestjs/common';
|
||||||
import { Endpoint } from '@/server/api/endpoint-base.js';
|
import { Endpoint } from '@/server/api/endpoint-base.js';
|
||||||
import type { UsersRepository, UserProfilesRepository } from '@/models/_.js';
|
import type { UserProfilesRepository } from '@/models/_.js';
|
||||||
import { DI } from '@/di-symbols.js';
|
import { DI } from '@/di-symbols.js';
|
||||||
|
import { CacheService } from '@/core/CacheService.js';
|
||||||
|
import { ModerationLogService } from '@/core/ModerationLogService.js';
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
tags: ['admin'],
|
tags: ['admin'],
|
||||||
|
@ -27,18 +29,19 @@ export const paramDef = {
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-disable-line import/no-default-export
|
export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-disable-line import/no-default-export
|
||||||
constructor(
|
constructor(
|
||||||
@Inject(DI.usersRepository)
|
private readonly cacheService: CacheService,
|
||||||
private usersRepository: UsersRepository,
|
private readonly moderationLogService: ModerationLogService,
|
||||||
|
|
||||||
@Inject(DI.userProfilesRepository)
|
@Inject(DI.userProfilesRepository)
|
||||||
private userProfilesRepository: UserProfilesRepository,
|
private readonly userProfilesRepository: UserProfilesRepository,
|
||||||
) {
|
) {
|
||||||
super(meta, paramDef, async (ps, me) => {
|
super(meta, paramDef, async (ps, me) => {
|
||||||
const user = await this.usersRepository.findOneBy({ id: ps.userId });
|
const user = await this.cacheService.findUserById(ps.userId);
|
||||||
|
|
||||||
if (user == null) {
|
await this.moderationLogService.log(me, 'unNsfwUser', {
|
||||||
throw new Error('user not found');
|
userId: ps.userId,
|
||||||
}
|
userUsername: user.username,
|
||||||
|
userHost: user.host,
|
||||||
|
});
|
||||||
|
|
||||||
await this.userProfilesRepository.update(user.id, {
|
await this.userProfilesRepository.update(user.id, {
|
||||||
alwaysMarkNsfw: false,
|
alwaysMarkNsfw: false,
|
||||||
|
|
|
@ -7,6 +7,9 @@ import { Inject, Injectable } from '@nestjs/common';
|
||||||
import { Endpoint } from '@/server/api/endpoint-base.js';
|
import { Endpoint } from '@/server/api/endpoint-base.js';
|
||||||
import type { UsersRepository } from '@/models/_.js';
|
import type { UsersRepository } from '@/models/_.js';
|
||||||
import { DI } from '@/di-symbols.js';
|
import { DI } from '@/di-symbols.js';
|
||||||
|
import { ModerationLogService } from '@/core/ModerationLogService.js';
|
||||||
|
import { CacheService } from '@/core/CacheService.js';
|
||||||
|
import { GlobalEventService } from '@/core/GlobalEventService.js';
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
tags: ['admin'],
|
tags: ['admin'],
|
||||||
|
@ -28,18 +31,27 @@ export const paramDef = {
|
||||||
export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-disable-line import/no-default-export
|
export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-disable-line import/no-default-export
|
||||||
constructor(
|
constructor(
|
||||||
@Inject(DI.usersRepository)
|
@Inject(DI.usersRepository)
|
||||||
private usersRepository: UsersRepository,
|
private readonly usersRepository: UsersRepository,
|
||||||
|
private readonly cacheService: CacheService,
|
||||||
|
private readonly moderationLogService: ModerationLogService,
|
||||||
|
private readonly globalEventService: GlobalEventService,
|
||||||
) {
|
) {
|
||||||
super(meta, paramDef, async (ps, me) => {
|
super(meta, paramDef, async (ps, me) => {
|
||||||
const user = await this.usersRepository.findOneBy({ id: ps.userId });
|
const user = await this.cacheService.findUserById(ps.userId);
|
||||||
|
|
||||||
if (user == null) {
|
await this.moderationLogService.log(me, 'unSilenceUser', {
|
||||||
throw new Error('user not found');
|
userId: ps.userId,
|
||||||
}
|
userUsername: user.username,
|
||||||
|
userHost: user.host,
|
||||||
|
});
|
||||||
|
|
||||||
await this.usersRepository.update(user.id, {
|
await this.usersRepository.update(user.id, {
|
||||||
isSilenced: false,
|
isSilenced: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.globalEventService.publishInternalEvent(user.host == null ? 'localUserUpdated' : 'remoteUserUpdated', {
|
||||||
|
id: user.id,
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,7 +78,6 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
||||||
flashId: flash.id,
|
flashId: flash.id,
|
||||||
flashUserId: flash.userId,
|
flashUserId: flash.userId,
|
||||||
flashUserUsername: user.username,
|
flashUserUsername: user.username,
|
||||||
flash,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -78,7 +78,6 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
||||||
postId: post.id,
|
postId: post.id,
|
||||||
postUserId: post.userId,
|
postUserId: post.userId,
|
||||||
postUserUsername: user.username,
|
postUserUsername: user.username,
|
||||||
post,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -79,7 +79,6 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
||||||
pageId: page.id,
|
pageId: page.id,
|
||||||
pageUserId: page.userId,
|
pageUserId: page.userId,
|
||||||
pageUserUsername: user.username,
|
pageUserUsername: user.username,
|
||||||
page,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -136,6 +136,21 @@ export const moderationLogTypes = [
|
||||||
'rejectQuotesUser',
|
'rejectQuotesUser',
|
||||||
'acceptQuotesInstance',
|
'acceptQuotesInstance',
|
||||||
'rejectQuotesInstance',
|
'rejectQuotesInstance',
|
||||||
|
'clearUserFiles',
|
||||||
|
'nsfwUser',
|
||||||
|
'unNsfwUser',
|
||||||
|
'silenceUser',
|
||||||
|
'unSilenceUser',
|
||||||
|
'createAccount',
|
||||||
|
'clearRemoteFiles',
|
||||||
|
'clearOwnerlessFiles',
|
||||||
|
'updateCustomEmojis',
|
||||||
|
'importCustomEmojis',
|
||||||
|
'clearInstanceFiles',
|
||||||
|
'severFollowRelations',
|
||||||
|
'createPromo',
|
||||||
|
'addRelay',
|
||||||
|
'removeRelay',
|
||||||
] as const;
|
] as const;
|
||||||
|
|
||||||
export type ModerationLogPayloads = {
|
export type ModerationLogPayloads = {
|
||||||
|
@ -224,7 +239,6 @@ export type ModerationLogPayloads = {
|
||||||
noteUserId: string;
|
noteUserId: string;
|
||||||
noteUserUsername: string;
|
noteUserUsername: string;
|
||||||
noteUserHost: string | null;
|
noteUserHost: string | null;
|
||||||
note: any;
|
|
||||||
};
|
};
|
||||||
createGlobalAnnouncement: {
|
createGlobalAnnouncement: {
|
||||||
announcementId: string;
|
announcementId: string;
|
||||||
|
@ -407,19 +421,16 @@ export type ModerationLogPayloads = {
|
||||||
pageId: string;
|
pageId: string;
|
||||||
pageUserId: string;
|
pageUserId: string;
|
||||||
pageUserUsername: string;
|
pageUserUsername: string;
|
||||||
page: any;
|
|
||||||
};
|
};
|
||||||
deleteFlash: {
|
deleteFlash: {
|
||||||
flashId: string;
|
flashId: string;
|
||||||
flashUserId: string;
|
flashUserId: string;
|
||||||
flashUserUsername: string;
|
flashUserUsername: string;
|
||||||
flash: any;
|
|
||||||
};
|
};
|
||||||
deleteGalleryPost: {
|
deleteGalleryPost: {
|
||||||
postId: string;
|
postId: string;
|
||||||
postUserId: string;
|
postUserId: string;
|
||||||
postUserUsername: string;
|
postUserUsername: string;
|
||||||
post: any;
|
|
||||||
};
|
};
|
||||||
acceptQuotesUser: {
|
acceptQuotesUser: {
|
||||||
userId: string,
|
userId: string,
|
||||||
|
@ -439,6 +450,70 @@ export type ModerationLogPayloads = {
|
||||||
id: string;
|
id: string;
|
||||||
host: string;
|
host: string;
|
||||||
};
|
};
|
||||||
|
clearUserFiles: {
|
||||||
|
userId: string;
|
||||||
|
userUsername: string;
|
||||||
|
userHost: string | null;
|
||||||
|
count: number;
|
||||||
|
};
|
||||||
|
nsfwUser: {
|
||||||
|
userId: string;
|
||||||
|
userUsername: string;
|
||||||
|
userHost: string | null;
|
||||||
|
};
|
||||||
|
unNsfwUser: {
|
||||||
|
userId: string;
|
||||||
|
userUsername: string;
|
||||||
|
userHost: string | null;
|
||||||
|
};
|
||||||
|
silenceUser: {
|
||||||
|
userId: string;
|
||||||
|
userUsername: string;
|
||||||
|
userHost: string | null;
|
||||||
|
};
|
||||||
|
unSilenceUser: {
|
||||||
|
userId: string;
|
||||||
|
userUsername: string;
|
||||||
|
userHost: string | null;
|
||||||
|
};
|
||||||
|
createAccount: {
|
||||||
|
userId: string;
|
||||||
|
userUsername: string;
|
||||||
|
};
|
||||||
|
clearRemoteFiles: Record<string, never>;
|
||||||
|
clearOwnerlessFiles: {
|
||||||
|
count: number;
|
||||||
|
};
|
||||||
|
updateCustomEmojis: {
|
||||||
|
ids: string[],
|
||||||
|
category?: string | null,
|
||||||
|
license?: string | null,
|
||||||
|
setAliases?: string[],
|
||||||
|
addAliases?: string[],
|
||||||
|
delAliases?: string[],
|
||||||
|
},
|
||||||
|
importCustomEmojis: {
|
||||||
|
fileName: string,
|
||||||
|
},
|
||||||
|
clearInstanceFiles: {
|
||||||
|
host: string;
|
||||||
|
count: number;
|
||||||
|
},
|
||||||
|
severFollowRelations: {
|
||||||
|
host: string;
|
||||||
|
},
|
||||||
|
createPromo: {
|
||||||
|
noteId: string,
|
||||||
|
noteUserId: string;
|
||||||
|
noteUserUsername: string;
|
||||||
|
noteUserHost: string | null;
|
||||||
|
},
|
||||||
|
addRelay: {
|
||||||
|
inbox: string;
|
||||||
|
},
|
||||||
|
removeRelay: {
|
||||||
|
inbox: string;
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export type Serialized<T> = {
|
export type Serialized<T> = {
|
||||||
|
|
49
packages/frontend/src/components/DynamicNote.vue
Normal file
49
packages/frontend/src/components/DynamicNote.vue
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
<!--
|
||||||
|
SPDX-FileCopyrightText: hazelnoot and other Sharkey contributors
|
||||||
|
SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
-->
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<XNote
|
||||||
|
ref="rootEl"
|
||||||
|
:note="note"
|
||||||
|
:pinned="pinned"
|
||||||
|
:mock="mock"
|
||||||
|
:withHardMute="withHardMute"
|
||||||
|
@reaction="emoji => emit('reaction', emoji)"
|
||||||
|
@removeReaction="emoji => emit('removeReaction', emoji)"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import * as Misskey from 'misskey-js';
|
||||||
|
import { computed, defineAsyncComponent, shallowRef } from 'vue';
|
||||||
|
import type { ComponentExposed } from 'vue-component-type-helpers';
|
||||||
|
import type MkNote from '@/components/MkNote.vue';
|
||||||
|
import type SkNote from '@/components/SkNote.vue';
|
||||||
|
import { defaultStore } from '@/store';
|
||||||
|
|
||||||
|
const XNote = computed(() =>
|
||||||
|
defineAsyncComponent(() =>
|
||||||
|
defaultStore.reactiveState.noteDesign.value === 'misskey'
|
||||||
|
? import('@/components/MkNote.vue')
|
||||||
|
: import('@/components/SkNote.vue'),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
const rootEl = shallowRef<ComponentExposed<typeof MkNote | typeof SkNote>>();
|
||||||
|
|
||||||
|
defineExpose({ rootEl });
|
||||||
|
|
||||||
|
defineProps<{
|
||||||
|
note: Misskey.entities.Note;
|
||||||
|
pinned?: boolean;
|
||||||
|
mock?: boolean;
|
||||||
|
withHardMute?: boolean;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(ev: 'reaction', emoji: string): void;
|
||||||
|
(ev: 'removeReaction', emoji: string): void;
|
||||||
|
}>();
|
||||||
|
</script>
|
69
packages/frontend/src/components/SkFetchNote.vue
Normal file
69
packages/frontend/src/components/SkFetchNote.vue
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
<!--
|
||||||
|
SPDX-FileCopyrightText: hazelnoot and other Sharkey contributors
|
||||||
|
SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
-->
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<MkLazy @show="showing = true">
|
||||||
|
<MkLoading v-if="state === 'loading'"/>
|
||||||
|
|
||||||
|
<div v-if="state === 'error'">{{ i18n.ts.cannotLoadNote }}</div>
|
||||||
|
|
||||||
|
<DynamicNote v-if="state === 'done' && note" :note="note"/>
|
||||||
|
</MkLazy>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, watch } from 'vue';
|
||||||
|
import * as Misskey from 'misskey-js';
|
||||||
|
import { i18n } from '@/i18n.js';
|
||||||
|
import { misskeyApi } from '@/scripts/misskey-api';
|
||||||
|
import DynamicNote from '@/components/DynamicNote.vue';
|
||||||
|
|
||||||
|
const props = withDefaults(defineProps<{
|
||||||
|
noteId: string,
|
||||||
|
lazy?: boolean,
|
||||||
|
}>(), {
|
||||||
|
lazy: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Lazy-load, unless props.lazy is false.
|
||||||
|
// eslint-disable-next-line vue/no-setup-props-reactivity-loss
|
||||||
|
const showing = ref(!props.lazy);
|
||||||
|
const state = ref<'loading' | 'error' | 'done'>('loading');
|
||||||
|
const note = ref<Misskey.entities.Note | null>(null);
|
||||||
|
|
||||||
|
watch(
|
||||||
|
[
|
||||||
|
() => props.noteId,
|
||||||
|
() => showing.value,
|
||||||
|
],
|
||||||
|
async ([noteId, show]) => {
|
||||||
|
// Wait until the note is visible to avoid bombarding the API with requests.
|
||||||
|
if (!show) return;
|
||||||
|
|
||||||
|
// Unload the old note
|
||||||
|
note.value = null;
|
||||||
|
state.value = 'loading';
|
||||||
|
|
||||||
|
// Fetch the new note
|
||||||
|
const newNote = await misskeyApi('notes/show', { noteId }).catch(() => null);
|
||||||
|
|
||||||
|
// Check for race conditions (ex. the note changed again while the first request was still running)
|
||||||
|
if (noteId !== props.noteId) return;
|
||||||
|
|
||||||
|
// Check for errors
|
||||||
|
if (!newNote) {
|
||||||
|
state.value = 'error';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Display the new note
|
||||||
|
note.value = newNote;
|
||||||
|
state.value = 'done';
|
||||||
|
},
|
||||||
|
{
|
||||||
|
immediate: true,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
</script>
|
|
@ -16,10 +16,20 @@ import { nextTick, onMounted, onActivated, onBeforeUnmount, ref, shallowRef } fr
|
||||||
const rootEl = shallowRef<HTMLDivElement>();
|
const rootEl = shallowRef<HTMLDivElement>();
|
||||||
const showing = ref(false);
|
const showing = ref(false);
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(ev: 'show'): void,
|
||||||
|
}>();
|
||||||
|
|
||||||
const observer = new IntersectionObserver(
|
const observer = new IntersectionObserver(
|
||||||
(entries) => {
|
(entries) => {
|
||||||
if (entries.some((entry) => entry.isIntersecting)) {
|
if (entries.some((entry) => entry.isIntersecting)) {
|
||||||
showing.value = true;
|
showing.value = true;
|
||||||
|
|
||||||
|
// Disconnect to avoid observer soft-leaks
|
||||||
|
observer.disconnect();
|
||||||
|
|
||||||
|
// Notify containing element to trigger edge logic
|
||||||
|
emit('show');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
|
@ -18,6 +18,10 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
'createAvatarDecoration',
|
'createAvatarDecoration',
|
||||||
'createSystemWebhook',
|
'createSystemWebhook',
|
||||||
'createAbuseReportNotificationRecipient',
|
'createAbuseReportNotificationRecipient',
|
||||||
|
'createAccount',
|
||||||
|
'importCustomEmojis',
|
||||||
|
'createPromo',
|
||||||
|
'addRelay',
|
||||||
].includes(log.type),
|
].includes(log.type),
|
||||||
[$style.logYellow]: [
|
[$style.logYellow]: [
|
||||||
'markSensitiveDriveFile',
|
'markSensitiveDriveFile',
|
||||||
|
@ -30,6 +34,11 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
'acceptRemoteInstanceReports',
|
'acceptRemoteInstanceReports',
|
||||||
'rejectQuotesUser',
|
'rejectQuotesUser',
|
||||||
'acceptQuotesUser',
|
'acceptQuotesUser',
|
||||||
|
'nsfwUser',
|
||||||
|
'unNsfwUser',
|
||||||
|
'silenceUser',
|
||||||
|
'unSilenceUser',
|
||||||
|
'updateCustomEmojis',
|
||||||
].includes(log.type),
|
].includes(log.type),
|
||||||
[$style.logRed]: [
|
[$style.logRed]: [
|
||||||
'suspend',
|
'suspend',
|
||||||
|
@ -49,6 +58,12 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
'deletePage',
|
'deletePage',
|
||||||
'deleteFlash',
|
'deleteFlash',
|
||||||
'deleteGalleryPost',
|
'deleteGalleryPost',
|
||||||
|
'clearUserFiles',
|
||||||
|
'clearRemoteFiles',
|
||||||
|
'clearOwnerlessFiles',
|
||||||
|
'clearInstanceFiles',
|
||||||
|
'severFollowRelations',
|
||||||
|
'removeRelay',
|
||||||
].includes(log.type)
|
].includes(log.type)
|
||||||
}"
|
}"
|
||||||
>{{ i18n.ts._moderationLogTypes[log.type] }}</b>
|
>{{ i18n.ts._moderationLogTypes[log.type] }}</b>
|
||||||
|
@ -100,6 +115,19 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<span v-else-if="log.type === 'deletePage'">: @{{ log.info.pageUserUsername }}</span>
|
<span v-else-if="log.type === 'deletePage'">: @{{ log.info.pageUserUsername }}</span>
|
||||||
<span v-else-if="log.type === 'deleteFlash'">: @{{ log.info.flashUserUsername }}</span>
|
<span v-else-if="log.type === 'deleteFlash'">: @{{ log.info.flashUserUsername }}</span>
|
||||||
<span v-else-if="log.type === 'deleteGalleryPost'">: @{{ log.info.postUserUsername }}</span>
|
<span v-else-if="log.type === 'deleteGalleryPost'">: @{{ log.info.postUserUsername }}</span>
|
||||||
|
<span v-else-if="log.type === 'clearUserFiles'">: @{{ log.info.userUsername }}{{ log.info.userHost ? '@' + log.info.userHost : '' }}</span>
|
||||||
|
<span v-else-if="log.type === 'nsfwUser'">: @{{ log.info.userUsername }}{{ log.info.userHost ? '@' + log.info.userHost : '' }}</span>
|
||||||
|
<span v-else-if="log.type === 'unNsfwUser'">: @{{ log.info.userUsername }}{{ log.info.userHost ? '@' + log.info.userHost : '' }}</span>
|
||||||
|
<span v-else-if="log.type === 'silenceUser'">: @{{ log.info.userUsername }}{{ log.info.userHost ? '@' + log.info.userHost : '' }}</span>
|
||||||
|
<span v-else-if="log.type === 'unSilenceUser'">: @{{ log.info.userUsername }}{{ log.info.userHost ? '@' + log.info.userHost : '' }}</span>
|
||||||
|
<span v-else-if="log.type === 'createAccount'">: @{{ log.info.userUsername }}</span>
|
||||||
|
<span v-else-if="log.type === 'clearOwnerlessFiles'">: {{ log.info.count }}</span>
|
||||||
|
<span v-else-if="log.type === 'importCustomEmojis'">: {{ log.info.fileName }}</span>
|
||||||
|
<span v-else-if="log.type === 'clearInstanceFiles'">: {{ log.info.host }}</span>
|
||||||
|
<span v-else-if="log.type === 'severFollowRelations'">: {{ log.info.host }}</span>
|
||||||
|
<span v-else-if="log.type === 'createPromo'">: @{{ log.info.noteUserUsername }}{{ log.info.noteUserHost ? '@' + log.info.noteUserHost : '' }}</span>
|
||||||
|
<span v-else-if="log.type === 'addRelay'">: {{ log.info.inbox }}</span>
|
||||||
|
<span v-else-if="log.type === 'removeRelay'">: {{ log.info.inbox }}</span>
|
||||||
</template>
|
</template>
|
||||||
<template v-if="log.user" #icon>
|
<template v-if="log.user" #icon>
|
||||||
<MkAvatar :user="log.user" :class="$style.avatar"/>
|
<MkAvatar :user="log.user" :class="$style.avatar"/>
|
||||||
|
@ -205,6 +233,47 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<CodeDiff :context="5" :hideHeader="true" :oldString="log.info.before ?? ''" :newString="log.info.after ?? ''" maxHeight="300px"/>
|
<CodeDiff :context="5" :hideHeader="true" :oldString="log.info.before ?? ''" :newString="log.info.after ?? ''" maxHeight="300px"/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
<template v-else-if="log.type === 'clearUserFiles'">
|
||||||
|
<div>{{ i18n.ts.user }}: <MkA :to="`/admin/user/${log.info.userId}`" class="_link">@{{ log.info.userUsername }}{{ log.info.userHost ? '@' + log.info.userHost : '' }}</MkA></div>
|
||||||
|
<div>{{ i18n.ts.filesRemoved }}: {{ log.info.count }}</div>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="log.type === 'nsfwUser'">
|
||||||
|
<div>{{ i18n.ts.user }}: <MkA :to="`/admin/user/${log.info.userId}`" class="_link">@{{ log.info.userUsername }}{{ log.info.userHost ? '@' + log.info.userHost : '' }}</MkA></div>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="log.type === 'unNsfwUser'">
|
||||||
|
<div>{{ i18n.ts.user }}: <MkA :to="`/admin/user/${log.info.userId}`" class="_link">@{{ log.info.userUsername }}{{ log.info.userHost ? '@' + log.info.userHost : '' }}</MkA></div>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="log.type === 'silenceUser'">
|
||||||
|
<div>{{ i18n.ts.user }}: <MkA :to="`/admin/user/${log.info.userId}`" class="_link">@{{ log.info.userUsername }}{{ log.info.userHost ? '@' + log.info.userHost : '' }}</MkA></div>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="log.type === 'unSilenceUser'">
|
||||||
|
<div>{{ i18n.ts.user }}: <MkA :to="`/admin/user/${log.info.userId}`" class="_link">@{{ log.info.userUsername }}{{ log.info.userHost ? '@' + log.info.userHost : '' }}</MkA></div>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="log.type === 'createAccount'">
|
||||||
|
<div>{{ i18n.ts.user }}: <MkA :to="`/admin/user/${log.info.userId}`" class="_link">@{{ log.info.userUsername }}</MkA></div>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="log.type === 'clearOwnerlessFiles'">
|
||||||
|
<div>{{ i18n.ts.filesRemoved }}: {{ log.info.count }}</div>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="log.type === 'importCustomEmojis'">
|
||||||
|
<div>{{ i18n.ts.fileImported }}: {{ log.info.fileName }}</div>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="log.type === 'clearInstanceFiles'">
|
||||||
|
<div>{{ i18n.ts.host }}: <MkA :to="`/instance-info/${log.info.host}`" class="_link">{{ log.info.host }}</MkA></div>
|
||||||
|
<div>{{ i18n.ts.filesRemoved }}: {{ log.info.count }}</div>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="log.type === 'severFollowRelations'">
|
||||||
|
<div>{{ i18n.ts.host }}: <MkA :to="`/instance-info/${log.info.host}`" class="_link">{{ log.info.host }}</MkA></div>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="log.type === 'createPromo'">
|
||||||
|
<SkFetchNote :noteId="log.info.noteId"/>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="log.type === 'addRelay'">
|
||||||
|
<div>{{ i18n.ts.inboxUrl }}: {{ log.info.inbox }}</div>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="log.type === 'removeRelay'">
|
||||||
|
<div>{{ i18n.ts.inboxUrl }}: {{ log.info.inbox }}</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary>raw</summary>
|
<summary>raw</summary>
|
||||||
|
@ -220,6 +289,7 @@ import { CodeDiff } from 'v-code-diff';
|
||||||
import JSON5 from 'json5';
|
import JSON5 from 'json5';
|
||||||
import { i18n } from '@/i18n.js';
|
import { i18n } from '@/i18n.js';
|
||||||
import MkFolder from '@/components/MkFolder.vue';
|
import MkFolder from '@/components/MkFolder.vue';
|
||||||
|
import SkFetchNote from '@/components/SkFetchNote.vue';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
log: Misskey.entities.ModerationLog;
|
log: Misskey.entities.ModerationLog;
|
||||||
|
|
|
@ -2728,6 +2728,51 @@ type ModerationLog = {
|
||||||
} | {
|
} | {
|
||||||
type: 'deleteGalleryPost';
|
type: 'deleteGalleryPost';
|
||||||
info: ModerationLogPayloads['deleteGalleryPost'];
|
info: ModerationLogPayloads['deleteGalleryPost'];
|
||||||
|
} | {
|
||||||
|
type: 'clearUserFiles';
|
||||||
|
info: ModerationLogPayloads['clearUserFiles'];
|
||||||
|
} | {
|
||||||
|
type: 'nsfwUser';
|
||||||
|
info: ModerationLogPayloads['nsfwUser'];
|
||||||
|
} | {
|
||||||
|
type: 'unNsfwUser';
|
||||||
|
info: ModerationLogPayloads['unNsfwUser'];
|
||||||
|
} | {
|
||||||
|
type: 'silenceUser';
|
||||||
|
info: ModerationLogPayloads['silenceUser'];
|
||||||
|
} | {
|
||||||
|
type: 'unSilenceUser';
|
||||||
|
info: ModerationLogPayloads['unSilenceUser'];
|
||||||
|
} | {
|
||||||
|
type: 'createAccount';
|
||||||
|
info: ModerationLogPayloads['createAccount'];
|
||||||
|
} | {
|
||||||
|
type: 'clearRemoteFiles';
|
||||||
|
info: ModerationLogPayloads['clearRemoteFiles'];
|
||||||
|
} | {
|
||||||
|
type: 'clearOwnerlessFiles';
|
||||||
|
info: ModerationLogPayloads['clearOwnerlessFiles'];
|
||||||
|
} | {
|
||||||
|
type: 'updateCustomEmojis';
|
||||||
|
info: ModerationLogPayloads['updateCustomEmojis'];
|
||||||
|
} | {
|
||||||
|
type: 'importCustomEmojis';
|
||||||
|
info: ModerationLogPayloads['importCustomEmojis'];
|
||||||
|
} | {
|
||||||
|
type: 'clearInstanceFiles';
|
||||||
|
info: ModerationLogPayloads['clearInstanceFiles'];
|
||||||
|
} | {
|
||||||
|
type: 'severFollowRelations';
|
||||||
|
info: ModerationLogPayloads['severFollowRelations'];
|
||||||
|
} | {
|
||||||
|
type: 'createPromo';
|
||||||
|
info: ModerationLogPayloads['createPromo'];
|
||||||
|
} | {
|
||||||
|
type: 'addRelay';
|
||||||
|
info: ModerationLogPayloads['addRelay'];
|
||||||
|
} | {
|
||||||
|
type: 'removeRelay';
|
||||||
|
info: ModerationLogPayloads['removeRelay'];
|
||||||
});
|
});
|
||||||
|
|
||||||
// @public (undocumented)
|
// @public (undocumented)
|
||||||
|
|
|
@ -4,12 +4,8 @@ import type {
|
||||||
Ad,
|
Ad,
|
||||||
Announcement,
|
Announcement,
|
||||||
EmojiDetailed,
|
EmojiDetailed,
|
||||||
Flash,
|
|
||||||
GalleryPost,
|
|
||||||
InviteCode,
|
InviteCode,
|
||||||
MetaDetailed,
|
MetaDetailed,
|
||||||
Note,
|
|
||||||
Page,
|
|
||||||
Role,
|
Role,
|
||||||
ReversiGameDetailed,
|
ReversiGameDetailed,
|
||||||
SystemWebhook,
|
SystemWebhook,
|
||||||
|
@ -295,7 +291,6 @@ export type ModerationLogPayloads = {
|
||||||
noteUserId: string;
|
noteUserId: string;
|
||||||
noteUserUsername: string;
|
noteUserUsername: string;
|
||||||
noteUserHost: string | null;
|
noteUserHost: string | null;
|
||||||
note: Note;
|
|
||||||
};
|
};
|
||||||
createGlobalAnnouncement: {
|
createGlobalAnnouncement: {
|
||||||
announcementId: string;
|
announcementId: string;
|
||||||
|
@ -478,19 +473,16 @@ export type ModerationLogPayloads = {
|
||||||
pageId: string;
|
pageId: string;
|
||||||
pageUserId: string;
|
pageUserId: string;
|
||||||
pageUserUsername: string;
|
pageUserUsername: string;
|
||||||
page: Page;
|
|
||||||
};
|
};
|
||||||
deleteFlash: {
|
deleteFlash: {
|
||||||
flashId: string;
|
flashId: string;
|
||||||
flashUserId: string;
|
flashUserId: string;
|
||||||
flashUserUsername: string;
|
flashUserUsername: string;
|
||||||
flash: Flash;
|
|
||||||
};
|
};
|
||||||
deleteGalleryPost: {
|
deleteGalleryPost: {
|
||||||
postId: string;
|
postId: string;
|
||||||
postUserId: string;
|
postUserId: string;
|
||||||
postUserUsername: string;
|
postUserUsername: string;
|
||||||
post: GalleryPost;
|
|
||||||
};
|
};
|
||||||
acceptQuotesUser: {
|
acceptQuotesUser: {
|
||||||
userId: string,
|
userId: string,
|
||||||
|
@ -510,4 +502,69 @@ export type ModerationLogPayloads = {
|
||||||
id: string;
|
id: string;
|
||||||
host: string;
|
host: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
clearUserFiles: {
|
||||||
|
userId: string;
|
||||||
|
userUsername: string;
|
||||||
|
userHost: string | null;
|
||||||
|
count: number;
|
||||||
|
};
|
||||||
|
nsfwUser: {
|
||||||
|
userId: string;
|
||||||
|
userUsername: string;
|
||||||
|
userHost: string | null;
|
||||||
|
};
|
||||||
|
unNsfwUser: {
|
||||||
|
userId: string;
|
||||||
|
userUsername: string;
|
||||||
|
userHost: string | null;
|
||||||
|
};
|
||||||
|
silenceUser: {
|
||||||
|
userId: string;
|
||||||
|
userUsername: string;
|
||||||
|
userHost: string | null;
|
||||||
|
};
|
||||||
|
unSilenceUser: {
|
||||||
|
userId: string;
|
||||||
|
userUsername: string;
|
||||||
|
userHost: string | null;
|
||||||
|
};
|
||||||
|
createAccount: {
|
||||||
|
userId: string;
|
||||||
|
userUsername: string;
|
||||||
|
};
|
||||||
|
clearRemoteFiles: Record<string, never>;
|
||||||
|
clearOwnerlessFiles: {
|
||||||
|
count: number;
|
||||||
|
};
|
||||||
|
updateCustomEmojis: {
|
||||||
|
ids: string[],
|
||||||
|
category?: string | null,
|
||||||
|
license?: string | null,
|
||||||
|
setAliases?: string[],
|
||||||
|
addAliases?: string[],
|
||||||
|
delAliases?: string[],
|
||||||
|
};
|
||||||
|
importCustomEmojis: {
|
||||||
|
fileName: string,
|
||||||
|
};
|
||||||
|
clearInstanceFiles: {
|
||||||
|
host: string;
|
||||||
|
count: number;
|
||||||
|
};
|
||||||
|
severFollowRelations: {
|
||||||
|
host: string;
|
||||||
|
};
|
||||||
|
createPromo: {
|
||||||
|
noteId: string,
|
||||||
|
noteUserId: string;
|
||||||
|
noteUserUsername: string;
|
||||||
|
noteUserHost: string | null;
|
||||||
|
};
|
||||||
|
addRelay: {
|
||||||
|
inbox: string;
|
||||||
|
};
|
||||||
|
removeRelay: {
|
||||||
|
inbox: string;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -228,6 +228,51 @@ export type ModerationLog = {
|
||||||
} | {
|
} | {
|
||||||
type: 'deleteGalleryPost';
|
type: 'deleteGalleryPost';
|
||||||
info: ModerationLogPayloads['deleteGalleryPost'];
|
info: ModerationLogPayloads['deleteGalleryPost'];
|
||||||
|
} | {
|
||||||
|
type: 'clearUserFiles';
|
||||||
|
info: ModerationLogPayloads['clearUserFiles'];
|
||||||
|
} | {
|
||||||
|
type: 'nsfwUser';
|
||||||
|
info: ModerationLogPayloads['nsfwUser'];
|
||||||
|
} | {
|
||||||
|
type: 'unNsfwUser';
|
||||||
|
info: ModerationLogPayloads['unNsfwUser'];
|
||||||
|
} | {
|
||||||
|
type: 'silenceUser';
|
||||||
|
info: ModerationLogPayloads['silenceUser'];
|
||||||
|
} | {
|
||||||
|
type: 'unSilenceUser';
|
||||||
|
info: ModerationLogPayloads['unSilenceUser'];
|
||||||
|
} | {
|
||||||
|
type: 'createAccount';
|
||||||
|
info: ModerationLogPayloads['createAccount'];
|
||||||
|
} | {
|
||||||
|
type: 'clearRemoteFiles';
|
||||||
|
info: ModerationLogPayloads['clearRemoteFiles'];
|
||||||
|
} | {
|
||||||
|
type: 'clearOwnerlessFiles';
|
||||||
|
info: ModerationLogPayloads['clearOwnerlessFiles'];
|
||||||
|
} | {
|
||||||
|
type: 'updateCustomEmojis';
|
||||||
|
info: ModerationLogPayloads['updateCustomEmojis'];
|
||||||
|
} | {
|
||||||
|
type: 'importCustomEmojis';
|
||||||
|
info: ModerationLogPayloads['importCustomEmojis'];
|
||||||
|
} | {
|
||||||
|
type: 'clearInstanceFiles';
|
||||||
|
info: ModerationLogPayloads['clearInstanceFiles'];
|
||||||
|
} | {
|
||||||
|
type: 'severFollowRelations';
|
||||||
|
info: ModerationLogPayloads['severFollowRelations'];
|
||||||
|
} | {
|
||||||
|
type: 'createPromo';
|
||||||
|
info: ModerationLogPayloads['createPromo'];
|
||||||
|
} | {
|
||||||
|
type: 'addRelay';
|
||||||
|
info: ModerationLogPayloads['addRelay'];
|
||||||
|
} | {
|
||||||
|
type: 'removeRelay';
|
||||||
|
info: ModerationLogPayloads['removeRelay'];
|
||||||
});
|
});
|
||||||
|
|
||||||
export type ServerStats = {
|
export type ServerStats = {
|
||||||
|
|
|
@ -169,6 +169,9 @@ pinnedOnly: "Pinned"
|
||||||
blockingYou: "Blocking you"
|
blockingYou: "Blocking you"
|
||||||
warnExternalUrl: "Show warning when opening external URLs"
|
warnExternalUrl: "Show warning when opening external URLs"
|
||||||
flash: "Flash"
|
flash: "Flash"
|
||||||
|
filesRemoved: "Files removed"
|
||||||
|
fileImported: "File imported"
|
||||||
|
cannotLoadNote: "Failed to load note"
|
||||||
_flash:
|
_flash:
|
||||||
contentHidden: "Flash Content Hidden"
|
contentHidden: "Flash Content Hidden"
|
||||||
poweredByRuffle: "Powered by Ruffle."
|
poweredByRuffle: "Powered by Ruffle."
|
||||||
|
@ -320,6 +323,22 @@ _moderationLogTypes:
|
||||||
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"
|
||||||
allowQuotesUser: "Allowed quote posts from user"
|
allowQuotesUser: "Allowed quote posts from user"
|
||||||
|
clearUserFiles: "Cleared a user's drive files"
|
||||||
|
nsfwUser: "Marked user as NSFW"
|
||||||
|
unNsfwUser: "Un-marked user as NSFW"
|
||||||
|
silenceUser: "Silenced user"
|
||||||
|
unSilenceUser: "Un-silenced user"
|
||||||
|
createAccount: "Created an account"
|
||||||
|
clearRemoteFiles: "Cleared remote drive files"
|
||||||
|
clearOwnerlessFiles: "Cleared owner-less drive files"
|
||||||
|
updateCustomEmojis: "Updated custom emojis"
|
||||||
|
importCustomEmojis: "Imported custom emojis"
|
||||||
|
clearInstanceFiles: "Cleared an instance's drive files"
|
||||||
|
severFollowRelations: "Severed follow relations with an instance"
|
||||||
|
createPromo: "Created a note promo"
|
||||||
|
addRelay: "Added a relay"
|
||||||
|
removeRelay: "Removed a relay"
|
||||||
|
|
||||||
_mfm:
|
_mfm:
|
||||||
uncommonFeature: "This is not a widespread feature, it may not display properly on most other fedi software, including other Misskey forks"
|
uncommonFeature: "This is not a widespread feature, it may not display properly on most other fedi software, including other Misskey forks"
|
||||||
intro: "MFM is a markup language used on Misskey, Sharkey, Firefish, Akkoma, and more that can be used in many places. Here you can view a list of all available MFM syntax."
|
intro: "MFM is a markup language used on Misskey, Sharkey, Firefish, Akkoma, and more that can be used in many places. Here you can view a list of all available MFM syntax."
|
||||||
|
|
Loading…
Add table
Reference in a new issue