From 94eb321431e9321e7baa062f0f378f3a03853098 Mon Sep 17 00:00:00 2001 From: naskya Date: Sun, 19 Mar 2023 07:22:28 +0000 Subject: [PATCH] feat: set license information for custom emojis (#9719) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes: #9711 (please check this issue first) I cherry-picked two commits ([1](https://github.com/misskey-dev/misskey/commit/8ae9d2eaa8b0842671558370f787902e94b7f5a3), [2](https://github.com/misskey-dev/misskey/commit/ed51209172441927d24339f0759a5badbee3c9b6)) from [Misskey](https://github.com/misskey-dev/misskey) and made a few changes. 「ライセンス」should be written as "License" in the following screenshots, but it has not yet been translated. It would be nice if we could include multiple lines of text, but I just ported what's been implemented so far in Misskey not to mess things up. This is my first pull request (aside from typo correction). Feel free to point out any issues! ![](https://cdn.discordapp.com/attachments/823878222897741868/1086372711841935440/2023-03-18_042011.png) ![](https://cdn.discordapp.com/attachments/823878222897741868/1086373178214981853/01.png) ![](https://cdn.discordapp.com/attachments/823878222897741868/1086373336709341246/2023-03-18_042629.png) Co-authored-by: syuilo Co-authored-by: naskya Reviewed-on: https://codeberg.org/calckey/calckey/pulls/9719 Co-authored-by: naskya Co-committed-by: naskya --- locales/en-US.yml | 1 + locales/ja-JP.yml | 1 + ...678945242650-add-props-for-custom-emoji.js | 11 +++++ packages/backend/src/models/entities/emoji.ts | 5 +++ .../backend/src/models/repositories/emoji.ts | 1 + packages/backend/src/models/schema/emoji.ts | 5 +++ .../processors/db/import-custom-emojis.ts | 1 + packages/backend/src/server/api/endpoints.ts | 4 ++ .../server/api/endpoints/admin/emoji/add.ts | 1 + .../server/api/endpoints/admin/emoji/copy.ts | 1 + .../api/endpoints/admin/emoji/list-remote.ts | 5 +++ .../server/api/endpoints/admin/emoji/list.ts | 5 +++ .../endpoints/admin/emoji/set-license-bulk.ts | 45 +++++++++++++++++++ .../api/endpoints/admin/emoji/update.ts | 5 +++ .../backend/src/server/api/endpoints/emoji.ts | 38 ++++++++++++++++ packages/client/src/components/MkDialog.vue | 5 ++- packages/client/src/os.ts | 34 ++++++++++++++ .../src/pages/admin/emoji-edit-dialog.vue | 7 +++ packages/client/src/pages/admin/emojis.vue | 13 ++++++ packages/client/src/pages/emojis.emoji.vue | 21 ++++++--- 20 files changed, 203 insertions(+), 6 deletions(-) create mode 100644 packages/backend/migration/1678945242650-add-props-for-custom-emoji.js create mode 100644 packages/backend/src/server/api/endpoints/admin/emoji/set-license-bulk.ts create mode 100644 packages/backend/src/server/api/endpoints/emoji.ts diff --git a/locales/en-US.yml b/locales/en-US.yml index 775327b47..f78d146d0 100644 --- a/locales/en-US.yml +++ b/locales/en-US.yml @@ -935,6 +935,7 @@ moveFromLabel: "Account you're moving from:" moveFromDescription: "This will set an alias of your old account so that you can move from that account to this current one. Do this BEFORE moving from your older account. Please enter the tag of the account formatted like @person@instance.com" migrationConfirm: "Are you absolutely sure you want to migrate your acccount to {account}? Once you do this, you won't be able to reverse it, and you won't be able to use your account normally again.\nAlso, please ensure that you've set this current account as the account you're moving from." defaultReaction: "Default emoji reaction for outgoing and incoming posts" +license: "License" _sensitiveMediaDetection: description: "Reduces the effort of server moderation through automatically recognizing NSFW media via Machine Learning. This will slightly increase the load on the server." diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index fe672c16e..59bf28d5a 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -935,6 +935,7 @@ moveFromLabel: "引っ越し元のアカウント:" moveFromDescription: "別のアカウントからこのアカウントにフォロワーを引き継いで引っ越したい場合、ここでエイリアスを作成しておく必要があります。必ず引っ越しを実行する前に作成してください!引っ越し元のアカウントをこのように入力してください:@person@instance.com" migrationConfirm: "本当にこのアカウントを {account} に引っ越しますか?一度引っ越しを行うと取り消せず、二度とこのアカウントを元の状態で使用することはできません。\nまた、引っ越し先のアカウントでエイリアスを作成したことを確認してください。" defaultReaction: "リモートとローカルの投稿に対するデフォルトの絵文字リアクション" +license: "ライセンス" _sensitiveMediaDetection: description: "機械学習を使って自動でセンシティブなメディアを検出し、モデレーションに役立てることができます。サーバーの負荷が少し増えます。" 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 000000000..656a92177 --- /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/models/entities/emoji.ts b/packages/backend/src/models/entities/emoji.ts index f251de897..231568696 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/repositories/emoji.ts b/packages/backend/src/models/repositories/emoji.ts index e868fe94f..6eabfe955 100644 --- a/packages/backend/src/models/repositories/emoji.ts +++ b/packages/backend/src/models/repositories/emoji.ts @@ -15,6 +15,7 @@ export const EmojiRepository = db.getRepository(Emoji).extend({ host: emoji.host, // || emoji.originalUrl してるのは後方互換性のため url: emoji.publicUrl || emoji.originalUrl, + license: emoji.license, }; }, diff --git a/packages/backend/src/models/schema/emoji.ts b/packages/backend/src/models/schema/emoji.ts index 1e1dab868..8994381b3 100644 --- a/packages/backend/src/models/schema/emoji.ts +++ b/packages/backend/src/models/schema/emoji.ts @@ -40,5 +40,10 @@ export const packedEmojiSchema = { optional: false, nullable: false, }, + license: { + type: "string", + optional: false, + nullable: true, + }, }, } as const; diff --git a/packages/backend/src/queue/processors/db/import-custom-emojis.ts b/packages/backend/src/queue/processors/db/import-custom-emojis.ts index 45ab5ea9a..373a3a2da 100644 --- a/packages/backend/src/queue/processors/db/import-custom-emojis.ts +++ b/packages/backend/src/queue/processors/db/import-custom-emojis.ts @@ -75,6 +75,7 @@ export async function importCustomEmojis( originalUrl: driveFile.url, publicUrl: driveFile.webpublicUrl ?? driveFile.url, type: driveFile.webpublicType ?? driveFile.type, + license: emojiInfo.license, }).then((x) => Emojis.findOneByOrFail(x.identifiers[0])); } diff --git a/packages/backend/src/server/api/endpoints.ts b/packages/backend/src/server/api/endpoints.ts index 7fb5fd320..bfafbaa62 100644 --- a/packages/backend/src/server/api/endpoints.ts +++ b/packages/backend/src/server/api/endpoints.ts @@ -29,6 +29,7 @@ import * as ep___admin_emoji_list from "./endpoints/admin/emoji/list.js"; import * as ep___admin_emoji_removeAliasesBulk from "./endpoints/admin/emoji/remove-aliases-bulk.js"; import * as ep___admin_emoji_setAliasesBulk from "./endpoints/admin/emoji/set-aliases-bulk.js"; import * as ep___admin_emoji_setCategoryBulk from "./endpoints/admin/emoji/set-category-bulk.js"; +import * as ep___admin_emoji_setLicenseBulk from "./endpoints/admin/emoji/set-license-bulk.js"; import * as ep___admin_emoji_update from "./endpoints/admin/emoji/update.js"; import * as ep___admin_federation_deleteAllFiles from "./endpoints/admin/federation/delete-all-files.js"; import * as ep___admin_federation_refreshRemoteInstanceMetadata from "./endpoints/admin/federation/refresh-remote-instance-metadata.js"; @@ -131,6 +132,7 @@ import * as ep___drive_folders_show from "./endpoints/drive/folders/show.js"; import * as ep___drive_folders_update from "./endpoints/drive/folders/update.js"; import * as ep___drive_stream from "./endpoints/drive/stream.js"; import * as ep___emailAddress_available from "./endpoints/email-address/available.js"; +import * as ep___emoji from "./endpoints/emoji.js"; import * as ep___endpoint from "./endpoints/endpoint.js"; import * as ep___endpoints from "./endpoints/endpoints.js"; import * as ep___exportCustomEmojis from "./endpoints/export-custom-emojis.js"; @@ -363,6 +365,7 @@ const eps = [ ["admin/emoji/remove-aliases-bulk", ep___admin_emoji_removeAliasesBulk], ["admin/emoji/set-aliases-bulk", ep___admin_emoji_setAliasesBulk], ["admin/emoji/set-category-bulk", ep___admin_emoji_setCategoryBulk], + ["admin/emoji/set-license-bulk", ep___admin_emoji_setLicenseBulk], ["admin/emoji/update", ep___admin_emoji_update], ["admin/federation/delete-all-files", ep___admin_federation_deleteAllFiles], [ @@ -471,6 +474,7 @@ const eps = [ ["drive/folders/update", ep___drive_folders_update], ["drive/stream", ep___drive_stream], ["email-address/available", ep___emailAddress_available], + ["emoji", ep___emoji], ["endpoint", ep___endpoint], ["endpoints", ep___endpoints], ["export-custom-emojis", ep___exportCustomEmojis], 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 601d754a0..bfc025834 100644 --- a/packages/backend/src/server/api/endpoints/admin/emoji/add.ts +++ b/packages/backend/src/server/api/endpoints/admin/emoji/add.ts @@ -49,6 +49,7 @@ export default define(meta, paramDef, async (ps, me) => { originalUrl: file.url, publicUrl: file.webpublicUrl ?? file.url, type: file.webpublicType ?? file.type, + license: null, }).then((x) => Emojis.findOneByOrFail(x.identifiers[0])); await db.queryResultCache!.remove(["meta_emojis"]); 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 4a7f2bc61..951158f7d 100644 --- a/packages/backend/src/server/api/endpoints/admin/emoji/copy.ts +++ b/packages/backend/src/server/api/endpoints/admin/emoji/copy.ts @@ -73,6 +73,7 @@ export default define(meta, paramDef, async (ps, me) => { originalUrl: driveFile.url, publicUrl: driveFile.webpublicUrl ?? driveFile.url, type: driveFile.webpublicType ?? driveFile.type, + license: emoji.license, }).then((x) => Emojis.findOneByOrFail(x.identifiers[0])); await db.queryResultCache!.remove(["meta_emojis"]); diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/list-remote.ts b/packages/backend/src/server/api/endpoints/admin/emoji/list-remote.ts index 63f60bc99..fae986dd9 100644 --- a/packages/backend/src/server/api/endpoints/admin/emoji/list-remote.ts +++ b/packages/backend/src/server/api/endpoints/admin/emoji/list-remote.ts @@ -55,6 +55,11 @@ export const meta = { optional: false, nullable: false, }, + license: { + type: "string", + optional: false, + nullable: true, + }, }, }, }, diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/list.ts b/packages/backend/src/server/api/endpoints/admin/emoji/list.ts index bc4f1d29f..aa49f1480 100644 --- a/packages/backend/src/server/api/endpoints/admin/emoji/list.ts +++ b/packages/backend/src/server/api/endpoints/admin/emoji/list.ts @@ -55,6 +55,11 @@ export const meta = { optional: false, nullable: false, }, + license: { + type: "string", + optional: false, + nullable: true, + }, }, }, }, diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/set-license-bulk.ts b/packages/backend/src/server/api/endpoints/admin/emoji/set-license-bulk.ts new file mode 100644 index 000000000..c98ca03fa --- /dev/null +++ b/packages/backend/src/server/api/endpoints/admin/emoji/set-license-bulk.ts @@ -0,0 +1,45 @@ +import define from "../../../define.js"; +import { Emojis } from "@/models/index.js"; +import { In } from "typeorm"; +import { ApiError } from "../../../error.js"; +import { db } from "@/db/postgre.js"; + +export const meta = { + tags: ["admin"], + + requireCredential: true, + requireModerator: true, +} as const; + +export const paramDef = { + type: "object", + properties: { + ids: { + type: "array", + items: { + type: "string", + format: "misskey:id", + }, + }, + license: { + type: "string", + nullable: true, + description: "Use `null` to reset the license.", + }, + }, + required: ["ids"], +} as const; + +export default define(meta, paramDef, async (ps) => { + await Emojis.update( + { + id: In(ps.ids), + }, + { + updatedAt: new Date(), + license: ps.license, + }, + ); + + await 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 3f7f6639f..9e2e85476 100644 --- a/packages/backend/src/server/api/endpoints/admin/emoji/update.ts +++ b/packages/backend/src/server/api/endpoints/admin/emoji/update.ts @@ -34,6 +34,10 @@ export const paramDef = { type: "string", }, }, + license: { + type: "string", + nullable: true, + }, }, required: ["id", "name", "aliases"], } as const; @@ -48,6 +52,7 @@ export default define(meta, paramDef, async (ps) => { name: ps.name, category: ps.category, aliases: ps.aliases, + license: ps.license, }); await db.queryResultCache!.remove(["meta_emojis"]); diff --git a/packages/backend/src/server/api/endpoints/emoji.ts b/packages/backend/src/server/api/endpoints/emoji.ts new file mode 100644 index 000000000..5d3c77e5e --- /dev/null +++ b/packages/backend/src/server/api/endpoints/emoji.ts @@ -0,0 +1,38 @@ +import { IsNull } from "typeorm"; +import { Emojis } from "@/models/index.js"; +import define from "../define.js"; + +export const meta = { + tags: ["meta"], + + requireCredential: false, + allowGet: true, + cacheSec: 3600, + + res: { + type: "object", + optional: false, nullable: false, + ref: "Emoji", + }, +} as const; + +export const paramDef = { + type: "object", + properties: { + name: { + type: "string", + }, + }, + required: ["name"], +} as const; + +export default define(meta, paramDef, async (ps, me) => { + const emoji = await Emojis.findOneOrFail({ + where: { + name: ps.name, + host: IsNull(), + }, + }); + + return Emojis.pack(emoji); +}); diff --git a/packages/client/src/components/MkDialog.vue b/packages/client/src/components/MkDialog.vue index 9f93d9f99..5d5ca1e8d 100644 --- a/packages/client/src/components/MkDialog.vue +++ b/packages/client/src/components/MkDialog.vue @@ -14,9 +14,11 @@
- + + + @@ -20,15 +20,26 @@ const props = defineProps<{ function menu(ev) { os.popupMenu([{ - type: 'label', - text: ':' + props.emoji.name + ':', + type: "label", + text: ":" + props.emoji.name + ":", }, { text: i18n.ts.copy, - icon: 'ph-clipboard-text ph-bold ph-lg', + icon: "ph-clipboard-text ph-bold ph-lg", action: () => { copyToClipboard(`:${props.emoji.name}:`); os.success(); - } + }, + }, { + text: i18n.ts.license, + icon: "ph-info ph-bold ph-lg", + action: () => { + os.apiGet("emoji", { name: props.emoji.name }).then(res => { + os.alert({ + type: "info", + text: `${res.license || i18n.ts.notSet}`, + }); + }); + }, }], ev.currentTarget ?? ev.target); }