enhance: convert svg to png of custom emojis

This commit is contained in:
syuilo 2022-01-21 18:47:02 +09:00
parent 43baafbebb
commit eec7e6500e
12 changed files with 49 additions and 59 deletions

View File

@ -0,0 +1,15 @@
const { MigrationInterface, QueryRunner } = require("typeorm");
module.exports = class emojiUrl1642611822809 {
name = 'emojiUrl1642611822809'
async up(queryRunner) {
await queryRunner.query(`ALTER TABLE "emoji" RENAME COLUMN "url" TO "originalUrl"`);
await queryRunner.query(`ALTER TABLE "emoji" ADD "publicUrl" character varying(512) NOT NULL DEFAULT ''`);
}
async down(queryRunner) {
await queryRunner.query(`ALTER TABLE "emoji" DROP COLUMN "publicUrl"`);
await queryRunner.query(`ALTER TABLE "emoji" RENAME COLUMN "originalUrl" TO "url"`);
}
}

View File

@ -62,7 +62,8 @@ export async function populateEmoji(emojiName: string, noteUserHost: string | nu
if (emoji == null) return null; if (emoji == null) return null;
const isLocal = emoji.host == null; const isLocal = emoji.host == null;
const url = isLocal ? emoji.url : `${config.url}/proxy/image.png?${query({ url: emoji.url })}`; const emojiUrl = emoji.publicUrl || emoji.originalUrl; // || emoji.originalUrl してるのは後方互換性のため
const url = isLocal ? emojiUrl : `${config.url}/proxy/image.png?${query({ url: emojiUrl })}`;
return { return {
name: emojiName, name: emojiName,
@ -116,7 +117,7 @@ export async function prefetchEmojis(emojis: { name: string; host: string | null
} }
const _emojis = emojisQuery.length > 0 ? await Emojis.find({ const _emojis = emojisQuery.length > 0 ? await Emojis.find({
where: emojisQuery, where: emojisQuery,
select: ['name', 'host', 'url'], select: ['name', 'host', 'originalUrl', 'publicUrl'],
}) : []; }) : [];
for (const emoji of _emojis) { for (const emoji of _emojis) {
cache.set(`${emoji.name} ${emoji.host}`, emoji); cache.set(`${emoji.name} ${emoji.host}`, emoji);

View File

@ -32,13 +32,19 @@ export class Emoji {
@Column('varchar', { @Column('varchar', {
length: 512, length: 512,
}) })
public url: string; public originalUrl: string;
@Column('varchar', {
length: 512,
})
public publicUrl: string;
@Column('varchar', { @Column('varchar', {
length: 512, nullable: true, length: 512, nullable: true,
}) })
public uri: string | null; public uri: string | null;
// publicUrlの方のtypeが入る
@Column('varchar', { @Column('varchar', {
length: 64, nullable: true, length: 64, nullable: true,
}) })

View File

@ -15,7 +15,8 @@ export class EmojiRepository extends Repository<Emoji> {
name: emoji.name, name: emoji.name,
category: emoji.category, category: emoji.category,
host: emoji.host, host: emoji.host,
url: emoji.url, // || emoji.originalUrl してるのは後方互換性のため
url: emoji.publicUrl || emoji.originalUrl,
}; };
} }

View File

@ -72,7 +72,7 @@ export async function exportCustomEmojis(job: Bull.Job, done: () => void): Promi
let downloaded = false; let downloaded = false;
try { try {
await downloadUrl(emoji.url, emojiPath); await downloadUrl(emoji.originalUrl, emojiPath);
downloaded = true; downloaded = true;
} catch (e) { // TODO: 何度か再試行 } catch (e) { // TODO: 何度か再試行
logger.error(e); logger.error(e);

View File

@ -67,8 +67,9 @@ export async function importCustomEmojis(job: Bull.Job<DbUserImportJobData>, don
category: emojiInfo.category, category: emojiInfo.category,
host: null, host: null,
aliases: emojiInfo.aliases, aliases: emojiInfo.aliases,
url: driveFile.url, originalUrl: driveFile.url,
type: driveFile.type, publicUrl: driveFile.webpublicUrl ?? driveFile.url,
type: driveFile.webpublicType ?? driveFile.type,
}).then(x => Emojis.findOneOrFail(x.identifiers[0])); }).then(x => Emojis.findOneOrFail(x.identifiers[0]));
} }

View File

@ -320,14 +320,15 @@ export async function extractEmojis(tags: IObject | IObject[], host: string): Pr
if ((tag.updated != null && exists.updatedAt == null) if ((tag.updated != null && exists.updatedAt == null)
|| (tag.id != null && exists.uri == null) || (tag.id != null && exists.uri == null)
|| (tag.updated != null && exists.updatedAt != null && new Date(tag.updated) > exists.updatedAt) || (tag.updated != null && exists.updatedAt != null && new Date(tag.updated) > exists.updatedAt)
|| (tag.icon!.url !== exists.url) || (tag.icon!.url !== exists.originalUrl)
) { ) {
await Emojis.update({ await Emojis.update({
host, host,
name, name,
}, { }, {
uri: tag.id, uri: tag.id,
url: tag.icon!.url, originalUrl: tag.icon!.url,
publicUrl: tag.icon!.url,
updatedAt: new Date(), updatedAt: new Date(),
}); });
@ -347,7 +348,8 @@ export async function extractEmojis(tags: IObject | IObject[], host: string): Pr
host, host,
name, name,
uri: tag.id, uri: tag.id,
url: tag.icon!.url, originalUrl: tag.icon!.url,
publicUrl: tag.icon!.url,
updatedAt: new Date(), updatedAt: new Date(),
aliases: [], aliases: [],
} as Partial<Emoji>).then(x => Emojis.findOneOrFail(x.identifiers[0])); } as Partial<Emoji>).then(x => Emojis.findOneOrFail(x.identifiers[0]));

View File

@ -9,6 +9,6 @@ export default (emoji: Emoji) => ({
icon: { icon: {
type: 'Image', type: 'Image',
mediaType: emoji.type || 'image/png', mediaType: emoji.type || 'image/png',
url: emoji.url, url: emoji.publicUrl || emoji.originalUrl, // || emoji.originalUrl してるのは後方互換性のため
}, },
}); });

View File

@ -45,8 +45,9 @@ export default define(meta, async (ps, me) => {
category: null, category: null,
host: null, host: null,
aliases: [], aliases: [],
url: file.url, originalUrl: file.url,
type: file.type, publicUrl: file.webpublicUrl ?? file.url,
type: file.webpublicType ?? file.type,
}).then(x => Emojis.findOneOrFail(x.identifiers[0])); }).then(x => Emojis.findOneOrFail(x.identifiers[0]));
await getConnection().queryResultCache!.remove(['meta_emojis']); await getConnection().queryResultCache!.remove(['meta_emojis']);

View File

@ -54,7 +54,7 @@ export default define(meta, async (ps, me) => {
try { try {
// Create file // Create file
driveFile = await uploadFromUrl(emoji.url, null, null, null, false, true); driveFile = await uploadFromUrl(emoji.originalUrl, null, null, null, false, true);
} catch (e) { } catch (e) {
throw new ApiError(); throw new ApiError();
} }
@ -65,9 +65,9 @@ export default define(meta, async (ps, me) => {
name: emoji.name, name: emoji.name,
host: null, host: null,
aliases: [], aliases: [],
url: driveFile.url, originalUrl: driveFile.url,
type: driveFile.type, publicUrl: driveFile.webpublicUrl ?? driveFile.url,
fileId: driveFile.id, type: driveFile.webpublicType ?? driveFile.type,
}).then(x => Emojis.findOneOrFail(x.identifiers[0])); }).then(x => Emojis.findOneOrFail(x.identifiers[0]));
await getConnection().queryResultCache!.remove(['meta_emojis']); await getConnection().queryResultCache!.remove(['meta_emojis']);

View File

@ -81,19 +81,15 @@ export default async (user: { id: User['id']; host: User['host']; }, note: Note,
name: decodedReaction.name, name: decodedReaction.name,
host: decodedReaction.host, host: decodedReaction.host,
}, },
select: ['name', 'host', 'url'], select: ['name', 'host', 'originalUrl', 'publicUrl'],
}); });
if (emoji) {
emoji = {
name: emoji.host ? `${emoji.name}@${emoji.host}` : `${emoji.name}@.`,
url: emoji.url,
} as any;
}
publishNoteStream(note.id, 'reacted', { publishNoteStream(note.id, 'reacted', {
reaction: decodedReaction.reaction, reaction: decodedReaction.reaction,
emoji: emoji, emoji: emoji != null ? {
name: emoji.host ? `${emoji.name}@${emoji.host}` : `${emoji.name}@.`,
url: emoji.publicUrl || emoji.originalUrl, // || emoji.originalUrl してるのは後方互換性のため
} : null,
userId: user.id, userId: user.id,
}); });

View File

@ -1,33 +0,0 @@
import { initDb } from '@/db/postgre';
import { genId } from '@/misc/gen-id';
async function main(name: string, url: string, alias?: string): Promise<any> {
await initDb();
const { Emojis } = await import('@/models/index');
const aliases = alias != null ? [ alias ] : [];
await Emojis.save({
id: genId(),
host: null,
name,
url,
aliases,
updatedAt: new Date(),
});
}
const args = process.argv.slice(2);
const name = args[0];
const url = args[1];
if (!name) throw new Error('require name');
if (!url) throw new Error('require url');
main(name, url).then(() => {
console.log('success');
process.exit(0);
}).catch(e => {
console.warn(e);
process.exit(1);
});