97 lines
2.9 KiB
JavaScript
97 lines
2.9 KiB
JavaScript
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
|
|
};
|
|
});
|