summaryrefslogtreecommitdiff
path: root/packages/backend
diff options
context:
space:
mode:
authorsyuilo <Syuilotan@yahoo.co.jp>2023-05-18 18:45:49 +0900
committersyuilo <Syuilotan@yahoo.co.jp>2023-05-18 18:45:49 +0900
commit7ce569424a67c786a4f44993ce74f06989eba9df (patch)
tree895e142f514452310382ce8c315feebcce27b1e9 /packages/backend
parentperf(backend): pre-compile regexp (diff)
downloadsharkey-7ce569424a67c786a4f44993ce74f06989eba9df.tar.gz
sharkey-7ce569424a67c786a4f44993ce74f06989eba9df.tar.bz2
sharkey-7ce569424a67c786a4f44993ce74f06989eba9df.zip
feat: カスタム絵文字ごとにそれをリアクションとして使えるロールを設定できるように
Diffstat (limited to 'packages/backend')
-rw-r--r--packages/backend/migration/1684386446061-emoji-improve.js15
-rw-r--r--packages/backend/src/core/CustomEmojiService.ts22
-rw-r--r--packages/backend/src/core/MfmService.ts2
-rw-r--r--packages/backend/src/core/ReactionService.ts51
-rw-r--r--packages/backend/src/core/WebfingerService.ts7
-rw-r--r--packages/backend/src/core/entities/EmojiEntityService.ts4
-rw-r--r--packages/backend/src/models/entities/Emoji.ts16
-rw-r--r--packages/backend/src/models/json-schema/emoji.ts21
-rw-r--r--packages/backend/src/queue/processors/ImportCustomEmojisProcessorService.ts3
-rw-r--r--packages/backend/src/server/api/endpoints/admin/emoji/add.ts31
-rw-r--r--packages/backend/src/server/api/endpoints/admin/emoji/update.ts27
-rw-r--r--packages/backend/test/unit/ReactionService.ts42
12 files changed, 186 insertions, 55 deletions
diff --git a/packages/backend/migration/1684386446061-emoji-improve.js b/packages/backend/migration/1684386446061-emoji-improve.js
new file mode 100644
index 0000000000..40b0a2bc5e
--- /dev/null
+++ b/packages/backend/migration/1684386446061-emoji-improve.js
@@ -0,0 +1,15 @@
+export class EmojiImprove1684386446061 {
+ name = 'EmojiImprove1684386446061'
+
+ async up(queryRunner) {
+ await queryRunner.query(`ALTER TABLE "emoji" ADD "localOnly" boolean NOT NULL DEFAULT false`);
+ await queryRunner.query(`ALTER TABLE "emoji" ADD "isSensitive" boolean NOT NULL DEFAULT false`);
+ await queryRunner.query(`ALTER TABLE "emoji" ADD "roleIdsThatCanBeUsedThisEmojiAsReaction" character varying(128) array NOT NULL DEFAULT '{}'`);
+ }
+
+ async down(queryRunner) {
+ await queryRunner.query(`ALTER TABLE "emoji" DROP COLUMN "roleIdsThatCanBeUsedThisEmojiAsReaction"`);
+ await queryRunner.query(`ALTER TABLE "emoji" DROP COLUMN "isSensitive"`);
+ await queryRunner.query(`ALTER TABLE "emoji" DROP COLUMN "localOnly"`);
+ }
+}
diff --git a/packages/backend/src/core/CustomEmojiService.ts b/packages/backend/src/core/CustomEmojiService.ts
index 93557ce617..3499df38b7 100644
--- a/packages/backend/src/core/CustomEmojiService.ts
+++ b/packages/backend/src/core/CustomEmojiService.ts
@@ -7,7 +7,7 @@ import { EmojiEntityService } from '@/core/entities/EmojiEntityService.js';
import { GlobalEventService } from '@/core/GlobalEventService.js';
import type { DriveFile } from '@/models/entities/DriveFile.js';
import type { Emoji } from '@/models/entities/Emoji.js';
-import type { EmojisRepository } from '@/models/index.js';
+import type { EmojisRepository, Role } from '@/models/index.js';
import { bindThis } from '@/decorators.js';
import { MemoryKVCache, RedisSingleCache } from '@/misc/cache.js';
import { UtilityService } from '@/core/UtilityService.js';
@@ -15,6 +15,8 @@ import type { Config } from '@/config.js';
import { query } from '@/misc/prelude/url.js';
import type { Serialized } from '@/server/api/stream/types.js';
+const parseEmojiStrRegexp = /^(\w+)(?:@([\w.-]+))?$/;
+
@Injectable()
export class CustomEmojiService {
private cache: MemoryKVCache<Emoji | null>;
@@ -63,6 +65,9 @@ export class CustomEmojiService {
aliases: string[];
host: string | null;
license: string | null;
+ isSensitive: boolean;
+ localOnly: boolean;
+ roleIdsThatCanBeUsedThisEmojiAsReaction: Role['id'][];
}): Promise<Emoji> {
const emoji = await this.emojisRepository.insert({
id: this.idService.genId(),
@@ -75,6 +80,9 @@ export class CustomEmojiService {
publicUrl: data.driveFile.webpublicUrl ?? data.driveFile.url,
type: data.driveFile.webpublicType ?? data.driveFile.type,
license: data.license,
+ isSensitive: data.isSensitive,
+ localOnly: data.localOnly,
+ roleIdsThatCanBeUsedThisEmojiAsReaction: data.roleIdsThatCanBeUsedThisEmojiAsReaction,
}).then(x => this.emojisRepository.findOneByOrFail(x.identifiers[0]));
if (data.host == null) {
@@ -90,10 +98,14 @@ export class CustomEmojiService {
@bindThis
public async update(id: Emoji['id'], data: {
+ driveFile?: DriveFile;
name?: string;
category?: string | null;
aliases?: string[];
license?: string | null;
+ isSensitive?: boolean;
+ localOnly?: boolean;
+ roleIdsThatCanBeUsedThisEmojiAsReaction?: Role['id'][];
}): Promise<void> {
const emoji = await this.emojisRepository.findOneByOrFail({ id: id });
const sameNameEmoji = await this.emojisRepository.findOneBy({ name: data.name, host: IsNull() });
@@ -105,6 +117,12 @@ export class CustomEmojiService {
category: data.category,
aliases: data.aliases,
license: data.license,
+ isSensitive: data.isSensitive,
+ localOnly: data.localOnly,
+ originalUrl: data.driveFile != null ? data.driveFile.url : undefined,
+ publicUrl: data.driveFile != null ? (data.driveFile.webpublicUrl ?? data.driveFile.url) : undefined,
+ type: data.driveFile != null ? (data.driveFile.webpublicType ?? data.driveFile.type) : undefined,
+ roleIdsThatCanBeUsedThisEmojiAsReaction: data.roleIdsThatCanBeUsedThisEmojiAsReaction ?? undefined,
});
this.localEmojisCache.refresh();
@@ -259,7 +277,7 @@ export class CustomEmojiService {
@bindThis
public parseEmojiStr(emojiName: string, noteUserHost: string | null) {
- const match = emojiName.match(/^(\w+)(?:@([\w.-]+))?$/);
+ const match = emojiName.match(parseEmojiStrRegexp);
if (!match) return { name: null, host: null };
const name = match[1];
diff --git a/packages/backend/src/core/MfmService.ts b/packages/backend/src/core/MfmService.ts
index 9b2d5dc0ff..dffee16e08 100644
--- a/packages/backend/src/core/MfmService.ts
+++ b/packages/backend/src/core/MfmService.ts
@@ -83,7 +83,7 @@ export class MfmService {
if (hashtagNames && href && hashtagNames.map(x => x.toLowerCase()).includes(txt.toLowerCase())) {
text += txt;
// メンション
- } else if (txt.startsWith('@') && !(rel && rel.value.match(/^me /))) {
+ } else if (txt.startsWith('@') && !(rel && rel.value.startsWith('me '))) {
const part = txt.split('@');
if (part.length === 2 && href) {
diff --git a/packages/backend/src/core/ReactionService.ts b/packages/backend/src/core/ReactionService.ts
index 2184cfeb41..27334b33e6 100644
--- a/packages/backend/src/core/ReactionService.ts
+++ b/packages/backend/src/core/ReactionService.ts
@@ -20,6 +20,7 @@ import { bindThis } from '@/decorators.js';
import { UtilityService } from '@/core/UtilityService.js';
import { UserBlockingService } from '@/core/UserBlockingService.js';
import { CustomEmojiService } from '@/core/CustomEmojiService.js';
+import { RoleService } from '@/core/RoleService.js';
const FALLBACK = '❤';
@@ -75,6 +76,7 @@ export class ReactionService {
private utilityService: UtilityService,
private metaService: MetaService,
private customEmojiService: CustomEmojiService,
+ private roleService: RoleService,
private userEntityService: UserEntityService,
private noteEntityService: NoteEntityService,
private userBlockingService: UserBlockingService,
@@ -88,7 +90,7 @@ export class ReactionService {
}
@bindThis
- public async create(user: { id: User['id']; host: User['host']; isBot: User['isBot'] }, note: Note, reaction?: string | null) {
+ public async create(user: { id: User['id']; host: User['host']; isBot: User['isBot'] }, note: Note, _reaction?: string | null) {
// Check blocking
if (note.userId !== user.id) {
const blocked = await this.userBlockingService.checkBlocked(note.userId, user.id);
@@ -102,10 +104,36 @@ export class ReactionService {
throw new IdentifiableError('68e9d2d1-48bf-42c2-b90a-b20e09fd3d48', 'Note not accessible for you.');
}
+ let reaction = _reaction ?? FALLBACK;
+
if (note.reactionAcceptance === 'likeOnly' || ((note.reactionAcceptance === 'likeOnlyForRemote') && (user.host != null))) {
reaction = '❤️';
- } else {
- reaction = await this.toDbReaction(reaction, user.host);
+ } else if (_reaction) {
+ const custom = reaction.match(isCustomEmojiRegexp);
+ if (custom) {
+ const reacterHost = this.utilityService.toPunyNullable(user.host);
+
+ const name = custom[1];
+ const emoji = reacterHost == null
+ ? (await this.customEmojiService.localEmojisCache.fetch()).get(name)
+ : await this.emojisRepository.findOneBy({
+ host: reacterHost,
+ name,
+ });
+
+ if (emoji) {
+ if (emoji.roleIdsThatCanBeUsedThisEmojiAsReaction.length === 0 || (await this.roleService.getUserRoles(user.id)).some(r => emoji.roleIdsThatCanBeUsedThisEmojiAsReaction.includes(r.id))) {
+ reaction = reacterHost ? `:${name}@${reacterHost}:` : `:${name}:`;
+ } else {
+ // リアクションとして使う権限がない
+ reaction = FALLBACK;
+ }
+ } else {
+ reaction = FALLBACK;
+ }
+ } else {
+ reaction = this.normalize(reaction ?? null);
+ }
}
const record: NoteReaction = {
@@ -291,11 +319,9 @@ export class ReactionService {
}
@bindThis
- public async toDbReaction(reaction?: string | null, reacterHost?: string | null): Promise<string> {
+ public normalize(reaction: string | null): string {
if (reaction == null) return FALLBACK;
- reacterHost = this.utilityService.toPunyNullable(reacterHost);
-
// 文字列タイプのリアクションを絵文字に変換
if (Object.keys(legacies).includes(reaction)) return legacies[reaction];
@@ -309,19 +335,6 @@ export class ReactionService {
return unicode.match('\u200d') ? unicode : unicode.replace(/\ufe0f/g, '');
}
- const custom = reaction.match(isCustomEmojiRegexp);
- if (custom) {
- const name = custom[1];
- const emoji = reacterHost == null
- ? (await this.customEmojiService.localEmojisCache.fetch()).get(name)
- : await this.emojisRepository.findOneBy({
- host: reacterHost,
- name,
- });
-
- if (emoji) return reacterHost ? `:${name}@${reacterHost}:` : `:${name}:`;
- }
-
return FALLBACK;
}
diff --git a/packages/backend/src/core/WebfingerService.ts b/packages/backend/src/core/WebfingerService.ts
index 3ee7990643..f58a6a10fc 100644
--- a/packages/backend/src/core/WebfingerService.ts
+++ b/packages/backend/src/core/WebfingerService.ts
@@ -16,6 +16,9 @@ type IWebFinger = {
subject: string;
};
+const urlRegex = /^https?:\/\//;
+const mRegex = /^([^@]+)@(.*)/;
+
@Injectable()
export class WebfingerService {
constructor(
@@ -35,12 +38,12 @@ export class WebfingerService {
@bindThis
private genUrl(query: string): string {
- if (query.match(/^https?:\/\//)) {
+ if (query.match(urlRegex)) {
const u = new URL(query);
return `${u.protocol}//${u.hostname}/.well-known/webfinger?` + urlQuery({ resource: query });
}
- const m = query.match(/^([^@]+)@(.*)/);
+ const m = query.match(mRegex);
if (m) {
const hostname = m[2];
const useHttp = process.env.MISSKEY_WEBFINGER_USE_HTTP && process.env.MISSKEY_WEBFINGER_USE_HTTP.toLowerCase() === 'true';
diff --git a/packages/backend/src/core/entities/EmojiEntityService.ts b/packages/backend/src/core/entities/EmojiEntityService.ts
index 3bad048bc0..0c7bd9ed9a 100644
--- a/packages/backend/src/core/entities/EmojiEntityService.ts
+++ b/packages/backend/src/core/entities/EmojiEntityService.ts
@@ -26,6 +26,7 @@ export class EmojiEntityService {
category: emoji.category,
// || emoji.originalUrl してるのは後方互換性のため(publicUrlはstringなので??はだめ)
url: emoji.publicUrl || emoji.originalUrl,
+ isSensitive: emoji.isSensitive,
};
}
@@ -51,6 +52,9 @@ export class EmojiEntityService {
// || emoji.originalUrl してるのは後方互換性のため(publicUrlはstringなので??はだめ)
url: emoji.publicUrl || emoji.originalUrl,
license: emoji.license,
+ isSensitive: emoji.isSensitive,
+ localOnly: emoji.localOnly,
+ roleIdsThatCanBeUsedThisEmojiAsReaction: emoji.roleIdsThatCanBeUsedThisEmojiAsReaction,
};
}
diff --git a/packages/backend/src/models/entities/Emoji.ts b/packages/backend/src/models/entities/Emoji.ts
index dbb437d439..8fd3e65f5e 100644
--- a/packages/backend/src/models/entities/Emoji.ts
+++ b/packages/backend/src/models/entities/Emoji.ts
@@ -60,4 +60,20 @@ export class Emoji {
length: 1024, nullable: true,
})
public license: string | null;
+
+ @Column('boolean', {
+ default: false,
+ })
+ public localOnly: boolean;
+
+ @Column('boolean', {
+ default: false,
+ })
+ public isSensitive: boolean;
+
+ // TODO: 定期ジョブで存在しなくなったロールIDを除去するようにする
+ @Column('varchar', {
+ array: true, length: 128, default: '{}',
+ })
+ public roleIdsThatCanBeUsedThisEmojiAsReaction: string[];
}
diff --git a/packages/backend/src/models/json-schema/emoji.ts b/packages/backend/src/models/json-schema/emoji.ts
index db4fd62cf6..c59b5d1ef4 100644
--- a/packages/backend/src/models/json-schema/emoji.ts
+++ b/packages/backend/src/models/json-schema/emoji.ts
@@ -22,6 +22,10 @@ export const packedEmojiSimpleSchema = {
type: 'string',
optional: false, nullable: false,
},
+ isSensitive: {
+ type: 'boolean',
+ optional: false, nullable: false,
+ },
},
} as const;
@@ -63,5 +67,22 @@ export const packedEmojiDetailedSchema = {
type: 'string',
optional: false, nullable: true,
},
+ isSensitive: {
+ type: 'boolean',
+ optional: false, nullable: false,
+ },
+ localOnly: {
+ type: 'boolean',
+ optional: false, nullable: false,
+ },
+ roleIdsThatCanBeUsedThisEmojiAsReaction: {
+ type: 'array',
+ optional: false, nullable: false,
+ items: {
+ type: 'string',
+ optional: false, nullable: false,
+ format: 'id',
+ },
+ },
},
} as const;
diff --git a/packages/backend/src/queue/processors/ImportCustomEmojisProcessorService.ts b/packages/backend/src/queue/processors/ImportCustomEmojisProcessorService.ts
index cf78d8330c..600468a286 100644
--- a/packages/backend/src/queue/processors/ImportCustomEmojisProcessorService.ts
+++ b/packages/backend/src/queue/processors/ImportCustomEmojisProcessorService.ts
@@ -107,6 +107,9 @@ export class ImportCustomEmojisProcessorService {
aliases: emojiInfo.aliases,
driveFile,
license: emojiInfo.license,
+ isSensitive: emojiInfo.isSensitive,
+ localOnly: emojiInfo.localOnly,
+ roleIdsThatCanBeUsedThisEmojiAsReaction: [],
});
}
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 2fb3e489e7..509224e9c3 100644
--- a/packages/backend/src/server/api/endpoints/admin/emoji/add.ts
+++ b/packages/backend/src/server/api/endpoints/admin/emoji/add.ts
@@ -25,9 +25,24 @@ export const meta = {
export const paramDef = {
type: 'object',
properties: {
+ name: { type: 'string', pattern: '^[a-zA-Z0-9_]+$' },
fileId: { type: 'string', format: 'misskey:id' },
+ category: {
+ type: 'string',
+ nullable: true,
+ description: 'Use `null` to reset the category.',
+ },
+ aliases: { type: 'array', items: {
+ type: 'string',
+ } },
+ license: { type: 'string', nullable: true },
+ isSensitive: { type: 'boolean' },
+ localOnly: { type: 'boolean' },
+ roleIdsThatCanBeUsedThisEmojiAsReaction: { type: 'array', items: {
+ type: 'string',
+ } },
},
- required: ['fileId'],
+ required: ['name', 'fileId'],
} as const;
// TODO: ロジックをサービスに切り出す
@@ -45,18 +60,18 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
) {
super(meta, paramDef, async (ps, me) => {
const driveFile = await this.driveFilesRepository.findOneBy({ id: ps.fileId });
-
if (driveFile == null) throw new ApiError(meta.errors.noSuchFile);
- const name = driveFile.name.split('.')[0].match(/^[a-z0-9_]+$/) ? driveFile.name.split('.')[0] : `_${rndstr('a-z0-9', 8)}_`;
-
const emoji = await this.customEmojiService.add({
driveFile,
- name,
- category: null,
- aliases: [],
+ name: ps.name,
+ category: ps.category ?? null,
+ aliases: ps.aliases ?? [],
host: null,
- license: null,
+ license: ps.license ?? null,
+ isSensitive: ps.isSensitive ?? false,
+ localOnly: ps.localOnly ?? false,
+ roleIdsThatCanBeUsedThisEmojiAsReaction: ps.roleIdsThatCanBeUsedThisEmojiAsReaction ?? [],
});
this.moderationLogService.insertModerationLog(me, 'addEmoji', {
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 f63348b60b..fb22bdc477 100644
--- a/packages/backend/src/server/api/endpoints/admin/emoji/update.ts
+++ b/packages/backend/src/server/api/endpoints/admin/emoji/update.ts
@@ -1,6 +1,8 @@
import { Inject, Injectable } from '@nestjs/common';
import { Endpoint } from '@/server/api/endpoint-base.js';
import { CustomEmojiService } from '@/core/CustomEmojiService.js';
+import type { DriveFilesRepository } from '@/models/index.js';
+import { DI } from '@/di-symbols.js';
import { ApiError } from '../../../error.js';
export const meta = {
@@ -15,6 +17,11 @@ export const meta = {
code: 'NO_SUCH_EMOJI',
id: '684dec9d-a8c2-4364-9aa8-456c49cb1dc8',
},
+ noSuchFile: {
+ message: 'No such file.',
+ code: 'NO_SUCH_FILE',
+ id: '14fb9fd9-0731-4e2f-aeb9-f09e4740333d',
+ },
sameNameEmojiExists: {
message: 'Emoji that have same name already exists.',
code: 'SAME_NAME_EMOJI_EXISTS',
@@ -28,6 +35,7 @@ export const paramDef = {
properties: {
id: { type: 'string', format: 'misskey:id' },
name: { type: 'string', pattern: '^[a-zA-Z0-9_]+$' },
+ fileId: { type: 'string', format: 'misskey:id' },
category: {
type: 'string',
nullable: true,
@@ -37,6 +45,11 @@ export const paramDef = {
type: 'string',
} },
license: { type: 'string', nullable: true },
+ isSensitive: { type: 'boolean' },
+ localOnly: { type: 'boolean' },
+ roleIdsThatCanBeUsedThisEmojiAsReaction: { type: 'array', items: {
+ type: 'string',
+ } },
},
required: ['id', 'name', 'aliases'],
} as const;
@@ -45,14 +58,28 @@ export const paramDef = {
@Injectable()
export default class extends Endpoint<typeof meta, typeof paramDef> {
constructor(
+ @Inject(DI.driveFilesRepository)
+ private driveFilesRepository: DriveFilesRepository,
+
private customEmojiService: CustomEmojiService,
) {
super(meta, paramDef, async (ps, me) => {
+ let driveFile;
+
+ if (ps.fileId) {
+ driveFile = await this.driveFilesRepository.findOneBy({ id: ps.fileId });
+ if (driveFile == null) throw new ApiError(meta.errors.noSuchFile);
+ }
+
await this.customEmojiService.update(ps.id, {
+ driveFile,
name: ps.name,
category: ps.category ?? null,
aliases: ps.aliases,
license: ps.license ?? null,
+ isSensitive: ps.isSensitive,
+ localOnly: ps.localOnly,
+ roleIdsThatCanBeUsedThisEmojiAsReaction: ps.roleIdsThatCanBeUsedThisEmojiAsReaction,
});
});
}
diff --git a/packages/backend/test/unit/ReactionService.ts b/packages/backend/test/unit/ReactionService.ts
index 38db081ac0..aa68f4117d 100644
--- a/packages/backend/test/unit/ReactionService.ts
+++ b/packages/backend/test/unit/ReactionService.ts
@@ -15,78 +15,74 @@ describe('ReactionService', () => {
reactionService = app.get<ReactionService>(ReactionService);
});
- describe('toDbReaction', () => {
+ describe('normalize', () => {
test('絵文字リアクションはそのまま', async () => {
- assert.strictEqual(await reactionService.toDbReaction('👍'), '👍');
- assert.strictEqual(await reactionService.toDbReaction('🍅'), '🍅');
+ assert.strictEqual(await reactionService.normalize('👍'), '👍');
+ assert.strictEqual(await reactionService.normalize('🍅'), '🍅');
});
test('既存のリアクションは絵文字化する pudding', async () => {
- assert.strictEqual(await reactionService.toDbReaction('pudding'), '🍮');
+ assert.strictEqual(await reactionService.normalize('pudding'), '🍮');
});
test('既存のリアクションは絵文字化する like', async () => {
- assert.strictEqual(await reactionService.toDbReaction('like'), '👍');
+ assert.strictEqual(await reactionService.normalize('like'), '👍');
});
test('既存のリアクションは絵文字化する love', async () => {
- assert.strictEqual(await reactionService.toDbReaction('love'), '❤');
+ assert.strictEqual(await reactionService.normalize('love'), '❤');
});
test('既存のリアクションは絵文字化する laugh', async () => {
- assert.strictEqual(await reactionService.toDbReaction('laugh'), '😆');
+ assert.strictEqual(await reactionService.normalize('laugh'), '😆');
});
test('既存のリアクションは絵文字化する hmm', async () => {
- assert.strictEqual(await reactionService.toDbReaction('hmm'), '🤔');
+ assert.strictEqual(await reactionService.normalize('hmm'), '🤔');
});
test('既存のリアクションは絵文字化する surprise', async () => {
- assert.strictEqual(await reactionService.toDbReaction('surprise'), '😮');
+ assert.strictEqual(await reactionService.normalize('surprise'), '😮');
});
test('既存のリアクションは絵文字化する congrats', async () => {
- assert.strictEqual(await reactionService.toDbReaction('congrats'), '🎉');
+ assert.strictEqual(await reactionService.normalize('congrats'), '🎉');
});
test('既存のリアクションは絵文字化する angry', async () => {
- assert.strictEqual(await reactionService.toDbReaction('angry'), '💢');
+ assert.strictEqual(await reactionService.normalize('angry'), '💢');
});
test('既存のリアクションは絵文字化する confused', async () => {
- assert.strictEqual(await reactionService.toDbReaction('confused'), '😥');
+ assert.strictEqual(await reactionService.normalize('confused'), '😥');
});
test('既存のリアクションは絵文字化する rip', async () => {
- assert.strictEqual(await reactionService.toDbReaction('rip'), '😇');
+ assert.strictEqual(await reactionService.normalize('rip'), '😇');
});
test('既存のリアクションは絵文字化する star', async () => {
- assert.strictEqual(await reactionService.toDbReaction('star'), '⭐');
+ assert.strictEqual(await reactionService.normalize('star'), '⭐');
});
test('異体字セレクタ除去', async () => {
- assert.strictEqual(await reactionService.toDbReaction('㊗️'), '㊗');
+ assert.strictEqual(await reactionService.normalize('㊗️'), '㊗');
});
test('異体字セレクタ除去 必要なし', async () => {
- assert.strictEqual(await reactionService.toDbReaction('㊗'), '㊗');
- });
-
- test('fallback - undefined', async () => {
- assert.strictEqual(await reactionService.toDbReaction(undefined), '❤');
+ assert.strictEqual(await reactionService.normalize('㊗'), '㊗');
});
test('fallback - null', async () => {
- assert.strictEqual(await reactionService.toDbReaction(null), '❤');
+ assert.strictEqual(await reactionService.normalize(null), '❤');
});
test('fallback - empty', async () => {
- assert.strictEqual(await reactionService.toDbReaction(''), '❤');
+ assert.strictEqual(await reactionService.normalize(''), '❤');
});
test('fallback - unknown', async () => {
- assert.strictEqual(await reactionService.toDbReaction('unknown'), '❤');
+ assert.strictEqual(await reactionService.normalize('unknown'), '❤');
});
});
});