import define from "../../../define.js"; import { ApiError } from "../../../error.js"; import { DriveFiles, UserEmojis } from "../../../../../models/index.js"; import { genId } from "../../../../../misc/gen-id.js"; import { getEmojiSize } from "../../../../../misc/emoji-meta.js"; import { clearUserEmojiCache } from "../../../../../misc/populate-emojis.js"; function normalizeMimeType(type) { const mime = type?.split(";")[0]?.trim().toLowerCase(); return mime && mime.length <= 64 ? mime : null; } export const meta = { tags: [ "account" ], requireCredential: true, kind: "write:account", errors: { noSuchFile: { message: "No such file.", code: "NO_SUCH_FILE", id: "7be656a7-cb71-41a8-9904-e8b6481e61dd" }, notImage: { message: "The file is not an image.", code: "NOT_IMAGE", id: "64cfbb24-2628-4217-873d-09e22957cf49" }, alreadyExists: { message: "User emoji already exists.", code: "ALREADY_EXISTS", id: "259b6fdb-c603-4244-81cb-7218b967ab62" } } }; export const paramDef = { type: "object", properties: { name: { type: "string", pattern: "^[a-z0-9_]{1,64}$" }, fileId: { type: "string", format: "misskey:id" }, glyph: { type: "boolean", default: false } }, required: [ "name", "fileId" ] }; export default define(meta, paramDef, async (ps, me)=>{ const file = await DriveFiles.findOneBy({ id: ps.fileId, userId: me.id }); if (!file) throw new ApiError(meta.errors.noSuchFile); if (!file.type.startsWith("image/")) throw new ApiError(meta.errors.notImage); const exists = await UserEmojis.findOneBy({ name: ps.name, userId: me.id }); if (exists) throw new ApiError(meta.errors.alreadyExists); const size = await getEmojiSize(file.url).catch(()=>({ width: null, height: null })); const type = normalizeMimeType(file.webpublicType ?? file.type); const emoji = await UserEmojis.insert({ id: genId(), createdAt: new Date(), name: ps.name, userId: me.id, userGroupId: null, originalUrl: file.url, publicUrl: file.webpublicUrl ?? file.url, type, glyph: ps.glyph, width: size.width || null, height: size.height || null }).then((x)=>UserEmojis.findOneByOrFail(x.identifiers[0])); await clearUserEmojiCache(emoji.name, me.username, me.host); return { id: emoji.id, name: emoji.name, url: emoji.publicUrl || emoji.originalUrl, glyph: emoji.glyph, glyphUrl: emoji.glyph ? emoji.originalUrl : null, width: emoji.width, height: emoji.height }; });