mirror of
https://github.com/kokonect-link/cherrypick
synced 2025-01-19 08:13:14 +09:00
fix: emoji stealer
This commit is contained in:
parent
e757f716a6
commit
3903474f12
@ -39,6 +39,7 @@ import * as ep___admin_emoji_addAliasesBulk from './endpoints/admin/emoji/add-al
|
||||
import * as ep___admin_emoji_add from './endpoints/admin/emoji/add.js';
|
||||
import * as ep___admin_emoji_adds from './endpoints/admin/emoji/adds.js';
|
||||
import * as ep___admin_emoji_copy from './endpoints/admin/emoji/copy.js';
|
||||
import * as ep___admin_emoji_steal from './endpoints/admin/emoji/steal.js';
|
||||
import * as ep___admin_emoji_deleteBulk from './endpoints/admin/emoji/delete-bulk.js';
|
||||
import * as ep___admin_emoji_delete from './endpoints/admin/emoji/delete.js';
|
||||
import * as ep___admin_emoji_importZip from './endpoints/admin/emoji/import-zip.js';
|
||||
@ -430,6 +431,7 @@ const $admin_emoji_addAliasesBulk: Provider = { provide: 'ep:admin/emoji/add-ali
|
||||
const $admin_emoji_add: Provider = { provide: 'ep:admin/emoji/add', useClass: ep___admin_emoji_add.default };
|
||||
const $admin_emoji_adds: Provider = { provide: 'ep:admin/emoji/adds', useClass: ep___admin_emoji_adds.default };
|
||||
const $admin_emoji_copy: Provider = { provide: 'ep:admin/emoji/copy', useClass: ep___admin_emoji_copy.default };
|
||||
const $admin_emoji_steal: Provider = { provide: 'ep:admin/emoji/steal', useClass: ep___admin_emoji_steal.default };
|
||||
const $admin_emoji_deleteBulk: Provider = { provide: 'ep:admin/emoji/delete-bulk', useClass: ep___admin_emoji_deleteBulk.default };
|
||||
const $admin_emoji_delete: Provider = { provide: 'ep:admin/emoji/delete', useClass: ep___admin_emoji_delete.default };
|
||||
const $admin_emoji_importZip: Provider = { provide: 'ep:admin/emoji/import-zip', useClass: ep___admin_emoji_importZip.default };
|
||||
@ -826,6 +828,7 @@ const $retention: Provider = { provide: 'ep:retention', useClass: ep___retention
|
||||
$admin_emoji_add,
|
||||
$admin_emoji_adds,
|
||||
$admin_emoji_copy,
|
||||
$admin_emoji_steal,
|
||||
$admin_emoji_deleteBulk,
|
||||
$admin_emoji_delete,
|
||||
$admin_emoji_importZip,
|
||||
@ -1215,6 +1218,7 @@ const $retention: Provider = { provide: 'ep:retention', useClass: ep___retention
|
||||
$admin_emoji_add,
|
||||
$admin_emoji_adds,
|
||||
$admin_emoji_copy,
|
||||
$admin_emoji_steal,
|
||||
$admin_emoji_deleteBulk,
|
||||
$admin_emoji_delete,
|
||||
$admin_emoji_importZip,
|
||||
|
@ -38,6 +38,7 @@ import * as ep___admin_emoji_addAliasesBulk from './endpoints/admin/emoji/add-al
|
||||
import * as ep___admin_emoji_add from './endpoints/admin/emoji/add.js';
|
||||
import * as ep___admin_emoji_adds from './endpoints/admin/emoji/adds.js';
|
||||
import * as ep___admin_emoji_copy from './endpoints/admin/emoji/copy.js';
|
||||
import * as ep___admin_emoji_steal from './endpoints/admin/emoji/steal.js';
|
||||
import * as ep___admin_emoji_deleteBulk from './endpoints/admin/emoji/delete-bulk.js';
|
||||
import * as ep___admin_emoji_delete from './endpoints/admin/emoji/delete.js';
|
||||
import * as ep___admin_emoji_importZip from './endpoints/admin/emoji/import-zip.js';
|
||||
@ -427,6 +428,7 @@ const eps = [
|
||||
['admin/emoji/add', ep___admin_emoji_add],
|
||||
['admin/emoji/adds', ep___admin_emoji_adds],
|
||||
['admin/emoji/copy', ep___admin_emoji_copy],
|
||||
['admin/emoji/steal', ep___admin_emoji_steal],
|
||||
['admin/emoji/delete-bulk', ep___admin_emoji_deleteBulk],
|
||||
['admin/emoji/delete', ep___admin_emoji_delete],
|
||||
['admin/emoji/import-zip', ep___admin_emoji_importZip],
|
||||
|
112
packages/backend/src/server/api/endpoints/admin/emoji/steal.ts
Normal file
112
packages/backend/src/server/api/endpoints/admin/emoji/steal.ts
Normal file
@ -0,0 +1,112 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: syuilo and other misskey, cherrypick contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { Endpoint } from '@/server/api/endpoint-base.js';
|
||||
import type { EmojisRepository } from '@/models/index.js';
|
||||
import { IdService } from '@/core/IdService.js';
|
||||
import type { DriveFile } from '@/models/entities/DriveFile.js';
|
||||
import { DI } from '@/di-symbols.js';
|
||||
import { DriveService } from '@/core/DriveService.js';
|
||||
import { GlobalEventService } from '@/core/GlobalEventService.js';
|
||||
import { EmojiEntityService } from '@/core/entities/EmojiEntityService.js';
|
||||
import { ApiError } from '../../../error.js';
|
||||
import {IsNull} from "typeorm";
|
||||
|
||||
export const meta = {
|
||||
tags: ['admin'],
|
||||
|
||||
requireCredential: true,
|
||||
requireRolePolicy: 'canManageCustomEmojis',
|
||||
|
||||
errors: {
|
||||
noSuchEmoji: {
|
||||
message: 'No such emoji.',
|
||||
code: 'NO_SUCH_EMOJI',
|
||||
id: 'e2785b66-dca3-4087-9cac-b93c541cc425',
|
||||
},
|
||||
localEmojiAlreadyExists: {
|
||||
message: 'Local emoji already exists.',
|
||||
code: 'LOCAL_EMOJI_ALREADY_EXISTS',
|
||||
id: 'c7262375-102c-41c6-be6b-4f81166a8a5b',
|
||||
},
|
||||
},
|
||||
|
||||
res: {
|
||||
type: 'object',
|
||||
optional: false, nullable: false,
|
||||
properties: {
|
||||
id: {
|
||||
type: 'string',
|
||||
optional: false, nullable: false,
|
||||
format: 'id',
|
||||
},
|
||||
},
|
||||
},
|
||||
} as const;
|
||||
|
||||
export const paramDef = {
|
||||
type: 'object',
|
||||
properties: {
|
||||
name: { type: 'string' },
|
||||
host: { type: 'string' },
|
||||
},
|
||||
required: ['name', 'host'],
|
||||
} as const;
|
||||
|
||||
@Injectable()
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
export default class extends Endpoint<typeof meta, typeof paramDef> {
|
||||
constructor(
|
||||
@Inject(DI.emojisRepository)
|
||||
private emojisRepository: EmojisRepository,
|
||||
|
||||
private emojiEntityService: EmojiEntityService,
|
||||
private idService: IdService,
|
||||
private globalEventService: GlobalEventService,
|
||||
private driveService: DriveService,
|
||||
) {
|
||||
super(meta, paramDef, async (ps, me) => {
|
||||
const emoji = await this.emojisRepository.findOneBy({ name: ps.name, host: ps.host });
|
||||
const localEmoji = await this.emojisRepository.findOneBy({ name: ps.name, host: IsNull() });
|
||||
|
||||
if (emoji == null) {
|
||||
throw new ApiError(meta.errors.noSuchEmoji);
|
||||
}
|
||||
|
||||
if (localEmoji != null) {
|
||||
throw new ApiError(meta.errors.localEmojiAlreadyExists);
|
||||
}
|
||||
|
||||
let driveFile: DriveFile;
|
||||
|
||||
try {
|
||||
driveFile = await this.driveService.uploadFromUrl({ url: emoji.originalUrl, user: null, force: true });
|
||||
} catch (e) {
|
||||
throw new ApiError();
|
||||
}
|
||||
|
||||
const copied = await this.emojisRepository.insert({
|
||||
id: this.idService.genId(),
|
||||
updatedAt: new Date(),
|
||||
name: emoji.name,
|
||||
host: null,
|
||||
aliases: [],
|
||||
originalUrl: driveFile.url,
|
||||
publicUrl: driveFile.webpublicUrl ?? driveFile.url,
|
||||
type: driveFile.webpublicType ?? driveFile.type,
|
||||
license: emoji.license,
|
||||
}).then(x => this.emojisRepository.findOneByOrFail(x.identifiers[0]));
|
||||
|
||||
this.globalEventService.publishBroadcastStream('emojiAdded', {
|
||||
emoji: await this.emojiEntityService.packDetailed(copied.id),
|
||||
});
|
||||
|
||||
return {
|
||||
id: copied.id,
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
@ -58,6 +58,7 @@ export type Endpoints = {
|
||||
'admin/emoji/adds': { req: TODO; res: TODO; };
|
||||
'admin/emoji/copy': { req: TODO; res: TODO; };
|
||||
'admin/emoji/list-remote': { req: TODO; res: TODO; };
|
||||
'admin/emoji/steal': { req: TODO; res: TODO; };
|
||||
'admin/emoji/list': { req: TODO; res: TODO; };
|
||||
'admin/emoji/remove': { req: TODO; res: TODO; };
|
||||
'admin/emoji/update': { req: TODO; res: TODO; };
|
||||
|
@ -92,7 +92,16 @@ function onClick(ev: MouseEvent) {
|
||||
copyToClipboard(`:${props.name}:`);
|
||||
os.success();
|
||||
},
|
||||
}, ...(props.menuReaction && react ? [{
|
||||
}, ...(props.host && $i && ($i.isAdmin || $i.policies.canManageCustomEmojis) ? [{
|
||||
text: i18n.ts.import,
|
||||
icon: 'ti ti-plus',
|
||||
action: async () => {
|
||||
await os.apiWithDialog('admin/emoji/steal', {
|
||||
name: customEmojiName.value,
|
||||
host: props.host,
|
||||
});
|
||||
},
|
||||
}] : []), ...(props.menuReaction && react ? [{
|
||||
text: i18n.ts.doReaction,
|
||||
icon: 'ti ti-plus',
|
||||
action: () => {
|
||||
@ -123,37 +132,6 @@ onUnmounted(() => {
|
||||
window.removeEventListener('touchend', resetTimer);
|
||||
}
|
||||
});
|
||||
|
||||
const onContextMenu = (e: MouseEvent) => {
|
||||
if (props.host && $i && ($i.isAdmin || $i.policies.canManageCustomEmojis)) {
|
||||
os.contextMenu([
|
||||
{
|
||||
text: i18n.ts.import,
|
||||
icon: 'ti ti-plus',
|
||||
action: async () => {
|
||||
const id = ((await os.api('admin/emoji/list-remote', {
|
||||
host: props.host,
|
||||
name: props.name
|
||||
})) as { id: string }[])[0]?.id
|
||||
const localId = ((await os.api('admin/emoji/list', {
|
||||
name: props.name
|
||||
})) as { id: string }[])[0]?.id
|
||||
if (localId) {
|
||||
await os.alert({ type: 'error', title: 'Emoji already exists' })
|
||||
return
|
||||
}
|
||||
if (!id) {
|
||||
await os.alert({ type: 'error', title: 'Emoji not found' })
|
||||
return
|
||||
}
|
||||
await os.apiWithDialog('admin/emoji/copy', {
|
||||
emojiId: id,
|
||||
});
|
||||
}
|
||||
}
|
||||
], e)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" module>
|
||||
|
Loading…
Reference in New Issue
Block a user