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 e2454405fd..9e8b3b174e 100644 --- a/packages/backend/src/queue/processors/db/import-custom-emojis.ts +++ b/packages/backend/src/queue/processors/db/import-custom-emojis.ts @@ -11,6 +11,7 @@ import { addFile } from "@/services/drive/add-file.js"; import { genId } from "@/misc/gen-id.js"; import { db } from "@/db/postgre.js"; import probeImageSize from "probe-image-size"; +import * as path from "path"; const logger = queueLogger.createSubLogger("import-custom-emojis"); @@ -29,11 +30,11 @@ export async function importCustomEmojis( return; } - const [path, cleanup] = await createTempDir(); + const [tempPath, cleanup] = await createTempDir(); - logger.info(`Temp dir is ${path}`); + logger.info(`Temp dir is ${tempPath}`); - const destPath = `${path}/emojis.zip`; + const destPath = `${tempPath}/emojis.zip`; try { fs.writeFileSync(destPath, "", "binary"); @@ -46,44 +47,96 @@ export async function importCustomEmojis( throw e; } - const outputPath = `${path}/emojis`; + const outputPath = `${tempPath}/emojis`; const unzipStream = fs.createReadStream(destPath); const zip = new AdmZip(destPath); zip.extractAllToAsync(outputPath, true, false, async (error) => { if (error) throw error; - const metaRaw = fs.readFileSync(`${outputPath}/meta.json`, "utf-8"); - const meta = JSON.parse(metaRaw); - for (const record of meta.emojis) { - if (!record.downloaded) continue; - const emojiInfo = record.emoji; - const emojiPath = `${outputPath}/${record.fileName}`; - await Emojis.delete({ - name: emojiInfo.name, - }); - const driveFile = await addFile({ - user: null, - path: emojiPath, - name: record.fileName, - force: true, - }); - const file = fs.createReadStream(emojiPath); - const size = await probeImageSize(file); - file.destroy(); - await Emojis.insert({ - id: genId(), - updatedAt: new Date(), - name: emojiInfo.name, - category: emojiInfo.category, - host: null, - aliases: emojiInfo.aliases, - originalUrl: driveFile.url, - publicUrl: driveFile.webpublicUrl ?? driveFile.url, - type: driveFile.webpublicType ?? driveFile.type, - license: emojiInfo.license, - width: size.width || null, - height: size.height || null, - }).then((x) => Emojis.findOneByOrFail(x.identifiers[0])); + if (fs.existsSync(`${outputPath}/meta.json`)) { + logger.info("starting emoji import with metadata"); + const metaRaw = fs.readFileSync(`${outputPath}/meta.json`, "utf-8"); + const meta = JSON.parse(metaRaw); + + for (const record of meta.emojis) { + if (!record.downloaded) continue; + const emojiInfo = record.emoji; + const emojiPath = `${outputPath}/${record.fileName}`; + await Emojis.delete({ + name: emojiInfo.name, + }); + const driveFile = await addFile({ + user: null, + path: emojiPath, + name: record.fileName, + force: true, + }); + const file = fs.createReadStream(emojiPath); + const size = await probeImageSize(file); + file.destroy(); + await Emojis.insert({ + id: genId(), + updatedAt: new Date(), + name: emojiInfo.name, + category: emojiInfo.category, + host: null, + aliases: emojiInfo.aliases, + originalUrl: driveFile.url, + publicUrl: driveFile.webpublicUrl ?? driveFile.url, + type: driveFile.webpublicType ?? driveFile.type, + license: emojiInfo.license, + width: size.width || null, + height: size.height || null, + }).then((x) => Emojis.findOneByOrFail(x.identifiers[0])); + } + } else { + logger.info("starting emoji import without metadata"); + // Since we lack metadata, we import into a randomized category name instead + let categoryName = genId(); + + let containedEmojis = fs.readdirSync(outputPath); + + // Filter out accidental JSON files + containedEmojis = containedEmojis.filter( + (emoji) => !emoji.match(/\.(json)$/i), + ); + + for (const emojiFilename of containedEmojis) { + // strip extension and get filename to use as name + const name = path.basename(emojiFilename, path.extname(emojiFilename)); + const emojiPath = `${outputPath}/${emojiFilename}`; + + logger.info(`importing ${name}`); + + await Emojis.delete({ + name: name, + }); + const driveFile = await addFile({ + user: null, + path: emojiPath, + name: path.basename(emojiFilename), + force: true, + }); + const file = fs.createReadStream(emojiPath); + const size = await probeImageSize(file); + file.destroy(); + logger.info(`emoji size: ${size.width}x${size.height}`); + + await Emojis.insert({ + id: genId(), + updatedAt: new Date(), + name: name, + category: categoryName, + host: null, + aliases: [], + originalUrl: driveFile.url, + publicUrl: driveFile.webpublicUrl ?? driveFile.url, + type: driveFile.webpublicType ?? driveFile.type, + license: null, + width: size.width || null, + height: size.height || null, + }).then((x) => Emojis.findOneByOrFail(x.identifiers[0])); + } } await db.queryResultCache!.remove(["meta_emojis"]);