From 8ae9d2eaa8b0842671558370f787902e94b7f5a3 Mon Sep 17 00:00:00 2001
From: syuilo <Syuilotan@yahoo.co.jp>
Date: Thu, 16 Mar 2023 15:08:48 +0900
Subject: [PATCH] =?UTF-8?q?enhance:=20=E3=82=AB=E3=82=B9=E3=82=BF=E3=83=A0?=
 =?UTF-8?q?=E7=B5=B5=E6=96=87=E5=AD=97=E3=81=AB=E3=83=A9=E3=82=A4=E3=82=BB?=
 =?UTF-8?q?=E3=83=B3=E3=82=B9=E6=83=85=E5=A0=B1=E3=82=92=E4=BB=98=E4=B8=8E?=
 =?UTF-8?q?=E3=81=A7=E3=81=8D=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Resolve #10091
---
 CHANGELOG.md                                          |  1 +
 locales/ja-JP.yml                                     |  1 +
 .../1678945242650-add-props-for-custom-emoji.js       | 11 +++++++++++
 packages/backend/src/core/CustomEmojiService.ts       |  2 ++
 .../backend/src/core/entities/EmojiEntityService.ts   |  1 +
 packages/backend/src/models/entities/Emoji.ts         |  5 +++++
 packages/backend/src/models/json-schema/emoji.ts      |  4 ++++
 .../processors/ImportCustomEmojisProcessorService.ts  |  1 +
 .../src/server/api/endpoints/admin/emoji/add.ts       |  1 +
 .../src/server/api/endpoints/admin/emoji/copy.ts      |  1 +
 .../src/server/api/endpoints/admin/emoji/update.ts    |  2 ++
 packages/frontend/src/pages/emoji-edit-dialog.vue     |  6 ++++++
 12 files changed, 36 insertions(+)
 create mode 100644 packages/backend/migration/1678945242650-add-props-for-custom-emoji.js

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 78a990516c..e72d57db3b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -17,6 +17,7 @@ You should also include the user name that made the change.
 - ノートごとに絵文字リアクションを受け取るか設定できるように
 - ノート検索の利用可否をロールで制御可能に(デフォルトでオフ)
 - ロールの並び順を設定可能に
+- カスタム絵文字にライセンス情報を付与できるように
 - 指定した文字列を含む投稿の公開範囲をホームにできるように
 - enhance(client): 設定から自分のロールを確認できるように
 - enhance(client): DM作成時にメンションも含むように
diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml
index a3a1d2cd24..da10ec6693 100644
--- a/locales/ja-JP.yml
+++ b/locales/ja-JP.yml
@@ -974,6 +974,7 @@ resetPasswordConfirm: "パスワードリセットしますか?"
 sensitiveWords: "センシティブワード"
 sensitiveWordsDescription: "設定したワードが含まれるノートの公開範囲をホームにします。改行で区切って複数設定できます。"
 notesSearchNotAvailable: "ノート検索は利用できません。"
+license: "ライセンス"
 
 _achievements:
   earnedAt: "獲得日時"
diff --git a/packages/backend/migration/1678945242650-add-props-for-custom-emoji.js b/packages/backend/migration/1678945242650-add-props-for-custom-emoji.js
new file mode 100644
index 0000000000..656a921770
--- /dev/null
+++ b/packages/backend/migration/1678945242650-add-props-for-custom-emoji.js
@@ -0,0 +1,11 @@
+export class addPropsForCustomEmoji1678945242650 {
+    name = 'addPropsForCustomEmoji1678945242650'
+
+    async up(queryRunner) {
+        await queryRunner.query(`ALTER TABLE "emoji" ADD "license" character varying(1024)`);
+    }
+
+    async down(queryRunner) {
+        await queryRunner.query(`ALTER TABLE "emoji" DROP COLUMN "license"`);
+    }
+}
diff --git a/packages/backend/src/core/CustomEmojiService.ts b/packages/backend/src/core/CustomEmojiService.ts
index 4ef21e5117..b404848d7d 100644
--- a/packages/backend/src/core/CustomEmojiService.ts
+++ b/packages/backend/src/core/CustomEmojiService.ts
@@ -44,6 +44,7 @@ export class CustomEmojiService {
 		category: string | null;
 		aliases: string[];
 		host: string | null;
+		license: string | null;
 	}): Promise<Emoji> {
 		const emoji = await this.emojisRepository.insert({
 			id: this.idService.genId(),
@@ -55,6 +56,7 @@ export class CustomEmojiService {
 			originalUrl: data.driveFile.url,
 			publicUrl: data.driveFile.webpublicUrl ?? data.driveFile.url,
 			type: data.driveFile.webpublicType ?? data.driveFile.type,
+			license: data.license,
 		}).then(x => this.emojisRepository.findOneByOrFail(x.identifiers[0]));
 
 		if (data.host == null) {
diff --git a/packages/backend/src/core/entities/EmojiEntityService.ts b/packages/backend/src/core/entities/EmojiEntityService.ts
index 02e513fa3c..3bad048bc0 100644
--- a/packages/backend/src/core/entities/EmojiEntityService.ts
+++ b/packages/backend/src/core/entities/EmojiEntityService.ts
@@ -50,6 +50,7 @@ export class EmojiEntityService {
 			host: emoji.host,
 			// || emoji.originalUrl してるのは後方互換性のため(publicUrlはstringなので??はだめ)
 			url: emoji.publicUrl || emoji.originalUrl,
+			license: emoji.license,
 		};
 	}
 
diff --git a/packages/backend/src/models/entities/Emoji.ts b/packages/backend/src/models/entities/Emoji.ts
index 7332dd1857..dbb437d439 100644
--- a/packages/backend/src/models/entities/Emoji.ts
+++ b/packages/backend/src/models/entities/Emoji.ts
@@ -55,4 +55,9 @@ export class Emoji {
 		array: true, length: 128, default: '{}',
 	})
 	public aliases: string[];
+
+	@Column('varchar', {
+		length: 1024, nullable: true,
+	})
+	public license: string | null;
 }
diff --git a/packages/backend/src/models/json-schema/emoji.ts b/packages/backend/src/models/json-schema/emoji.ts
index c00c3dac1d..db4fd62cf6 100644
--- a/packages/backend/src/models/json-schema/emoji.ts
+++ b/packages/backend/src/models/json-schema/emoji.ts
@@ -59,5 +59,9 @@ export const packedEmojiDetailedSchema = {
 			type: 'string',
 			optional: false, nullable: false,
 		},
+		license: {
+			type: 'string',
+			optional: false, nullable: true,
+		},
 	},
 } as const;
diff --git a/packages/backend/src/queue/processors/ImportCustomEmojisProcessorService.ts b/packages/backend/src/queue/processors/ImportCustomEmojisProcessorService.ts
index 4ecf8daf74..ed96e9a525 100644
--- a/packages/backend/src/queue/processors/ImportCustomEmojisProcessorService.ts
+++ b/packages/backend/src/queue/processors/ImportCustomEmojisProcessorService.ts
@@ -102,6 +102,7 @@ export class ImportCustomEmojisProcessorService {
 					host: null,
 					aliases: emojiInfo.aliases,
 					driveFile,
+					license: emojiInfo.license,
 				});
 			}
 
diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/add.ts b/packages/backend/src/server/api/endpoints/admin/emoji/add.ts
index 04c58050ff..2fb3e489e7 100644
--- a/packages/backend/src/server/api/endpoints/admin/emoji/add.ts
+++ b/packages/backend/src/server/api/endpoints/admin/emoji/add.ts
@@ -56,6 +56,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
 				category: null,
 				aliases: [],
 				host: null,
+				license: null,
 			});
 
 			this.moderationLogService.insertModerationLog(me, 'addEmoji', {
diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/copy.ts b/packages/backend/src/server/api/endpoints/admin/emoji/copy.ts
index 6381a8743e..fea11a67d6 100644
--- a/packages/backend/src/server/api/endpoints/admin/emoji/copy.ts
+++ b/packages/backend/src/server/api/endpoints/admin/emoji/copy.ts
@@ -87,6 +87,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
 				originalUrl: driveFile.url,
 				publicUrl: driveFile.webpublicUrl ?? driveFile.url,
 				type: driveFile.webpublicType ?? driveFile.type,
+				license: emoji.license,
 			}).then(x => this.emojisRepository.findOneByOrFail(x.identifiers[0]));
 
 			await this.db.queryResultCache?.remove(['meta_emojis']);
diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/update.ts b/packages/backend/src/server/api/endpoints/admin/emoji/update.ts
index 02efb8710a..dad0e3ef86 100644
--- a/packages/backend/src/server/api/endpoints/admin/emoji/update.ts
+++ b/packages/backend/src/server/api/endpoints/admin/emoji/update.ts
@@ -35,6 +35,7 @@ export const paramDef = {
 		aliases: { type: 'array', items: {
 			type: 'string',
 		} },
+		license: { type: 'string', nullable: true },
 	},
 	required: ['id', 'name', 'aliases'],
 } as const;
@@ -64,6 +65,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
 				name: ps.name,
 				category: ps.category,
 				aliases: ps.aliases,
+				license: ps.license,
 			});
 
 			await this.db.queryResultCache?.remove(['meta_emojis']);
diff --git a/packages/frontend/src/pages/emoji-edit-dialog.vue b/packages/frontend/src/pages/emoji-edit-dialog.vue
index 9be30f76a0..84bc153b71 100644
--- a/packages/frontend/src/pages/emoji-edit-dialog.vue
+++ b/packages/frontend/src/pages/emoji-edit-dialog.vue
@@ -22,6 +22,9 @@
 				<template #label>{{ i18n.ts.tags }}</template>
 				<template #caption>{{ i18n.ts.setMultipleBySeparatingWithSpace }}</template>
 			</MkInput>
+			<MkInput v-model="license">
+				<template #label>{{ i18n.ts.license }}</template>
+			</MkInput>
 			<MkButton danger @click="del()"><i class="ti ti-trash"></i> {{ i18n.ts.delete }}</MkButton>
 		</div>
 	</MkSpacer>
@@ -45,6 +48,7 @@ let dialog = $ref(null);
 let name: string = $ref(props.emoji.name);
 let category: string = $ref(props.emoji.category);
 let aliases: string = $ref(props.emoji.aliases.join(' '));
+let license: string = $ref(props.emoji.license ?? '');
 
 const emit = defineEmits<{
 	(ev: 'done', v: { deleted?: boolean, updated?: any }): void,
@@ -61,6 +65,7 @@ async function update() {
 		name,
 		category,
 		aliases: aliases.split(' '),
+		license: license === '' ? null : license,
 	});
 
 	emit('done', {
@@ -69,6 +74,7 @@ async function update() {
 			name,
 			category,
 			aliases: aliases.split(' '),
+			license: license === '' ? null : license,
 		},
 	});
 
-- 
GitLab