hippofish/packages/backend/src/misc/reaction-lib.ts
ThatOneCalculator 6e8aa76f2d
chore: 🎨 format
2023-09-20 23:30:19 -07:00

92 lines
2.1 KiB
TypeScript

import { emojiRegex } from "./emoji-regex.js";
import { fetchMeta } from "./fetch-meta.js";
import { Emojis } from "@/models/index.js";
import { toPunyNullable } from "./convert-host.js";
import { IsNull } from "typeorm";
export async function getFallbackReaction() {
const meta = await fetchMeta();
return meta.defaultReaction;
}
export function convertReactions(reactions: Record<string, number>) {
const result = new Map();
for (const reaction in reactions) {
if (reactions[reaction] <= 0) continue;
const decoded = decodeReaction(reaction).reaction;
result.set(decoded, (result.get(decoded) || 0) + reactions[reaction]);
}
return Object.fromEntries(result);
}
export async function toDbReaction(
reaction?: string | null,
reacterHost?: string | null,
): Promise<string> {
if (!reaction) return await getFallbackReaction();
reacterHost = toPunyNullable(reacterHost);
if (reaction === "♥️") return "❤️";
// Allow unicode reactions
const match = emojiRegex.exec(reaction);
if (match) {
const unicode = match[0];
return unicode;
}
const custom = reaction.match(/^:([\w+-]+)(?:@\.)?:$/);
if (custom) {
const name = custom[1];
const emoji = await Emojis.findOneBy({
host: reacterHost || IsNull(),
name,
});
if (emoji) return reacterHost ? `:${name}@${reacterHost}:` : `:${name}:`;
}
return await getFallbackReaction();
}
type DecodedReaction = {
/**
* リアクション名 (Unicode Emoji or ':name@hostname' or ':name@.')
*/
reaction: string;
/**
* name (カスタム絵文字の場合name, Emojiクエリに使う)
*/
name?: string;
/**
* host (カスタム絵文字の場合host, Emojiクエリに使う)
*/
host?: string | null;
};
export function decodeReaction(str: string): DecodedReaction {
const custom = str.match(/^:([\w+-]+)(?:@([\w.-]+))?:$/);
if (custom) {
const name = custom[1];
const host = custom[2] || null;
return {
reaction: `:${name}@${host || "."}:`, // ローカル分は@以降を省略するのではなく.にする
name,
host,
};
}
return {
reaction: str,
name: undefined,
host: undefined,
};
}