summaryrefslogtreecommitdiff
path: root/src/remote
diff options
context:
space:
mode:
authorMeiMei <30769358+mei23@users.noreply.github.com>2018-11-02 08:59:40 +0900
committersyuilo <Syuilotan@yahoo.co.jp>2018-11-02 08:59:40 +0900
commit80b5fda292efd70cc749910e3672d50c9a70a72e (patch)
treea8f287c9c60a532112801d084fcb7d5b8c4e3650 /src/remote
parentFix bug (diff)
downloadsharkey-80b5fda292efd70cc749910e3672d50c9a70a72e.tar.gz
sharkey-80b5fda292efd70cc749910e3672d50c9a70a72e.tar.bz2
sharkey-80b5fda292efd70cc749910e3672d50c9a70a72e.zip
Remote custom emojis (#3074)
* Remote custom emojis * んほおおおおお
Diffstat (limited to 'src/remote')
-rw-r--r--src/remote/activitypub/misc/get-emoji-names.ts6
-rw-r--r--src/remote/activitypub/models/icon.ts5
-rw-r--r--src/remote/activitypub/models/note.ts39
-rw-r--r--src/remote/activitypub/models/tag.ts12
-rw-r--r--src/remote/activitypub/renderer/emoji.ts14
-rw-r--r--src/remote/activitypub/renderer/note.ts37
6 files changed, 108 insertions, 5 deletions
diff --git a/src/remote/activitypub/misc/get-emoji-names.ts b/src/remote/activitypub/misc/get-emoji-names.ts
new file mode 100644
index 0000000000..f744d02fed
--- /dev/null
+++ b/src/remote/activitypub/misc/get-emoji-names.ts
@@ -0,0 +1,6 @@
+import parse from '../../../mfm/parse';
+
+export default function(text: string) {
+ if (!text) return [];
+ return parse(text).filter(t => t.type === 'emoji').map(t => (t as any).emoji);
+}
diff --git a/src/remote/activitypub/models/icon.ts b/src/remote/activitypub/models/icon.ts
new file mode 100644
index 0000000000..50794a937d
--- /dev/null
+++ b/src/remote/activitypub/models/icon.ts
@@ -0,0 +1,5 @@
+export type IIcon = {
+ type: string;
+ mediaType?: string;
+ url?: string;
+};
diff --git a/src/remote/activitypub/models/note.ts b/src/remote/activitypub/models/note.ts
index d49cf53079..be6c1bcd18 100644
--- a/src/remote/activitypub/models/note.ts
+++ b/src/remote/activitypub/models/note.ts
@@ -10,6 +10,9 @@ import { resolvePerson, updatePerson } from './person';
import { resolveImage } from './image';
import { IRemoteUser, IUser } from '../../../models/user';
import htmlToMFM from '../../../mfm/html-to-mfm';
+import Emoji from '../../../models/emoji';
+import { ITag } from './tag';
+import { toUnicode } from 'punycode';
const log = debug('misskey:activitypub');
@@ -93,6 +96,10 @@ export async function createNote(value: any, resolver?: Resolver, silent = false
// テキストのパース
const text = note._misskey_content ? note._misskey_content : htmlToMFM(note.content);
+ await extractEmojis(note.tag, actor.host).catch(e => {
+ console.log(`extractEmojis: ${e}`);
+ });
+
// ユーザーの情報が古かったらついでに更新しておく
if (actor.updatedAt == null || Date.now() - actor.updatedAt.getTime() > 1000 * 60 * 60 * 24) {
updatePerson(note.attributedTo);
@@ -135,3 +142,35 @@ export async function resolveNote(value: string | IObject, resolver?: Resolver):
// 添付されてきたNote Objectは偽装されている可能性があるため、常にuriを指定してサーバーフェッチを行う。
return await createNote(uri, resolver);
}
+
+async function extractEmojis(tags: ITag[], host_: string) {
+ const host = toUnicode(host_.toLowerCase());
+
+ if (!tags) return [];
+
+ const eomjiTags = tags.filter(tag => tag.type === 'Emoji' && tag.icon && tag.icon.url);
+
+ return await Promise.all(
+ eomjiTags.map(async tag => {
+ const name = tag.name.replace(/^:/, '').replace(/:$/, '');
+
+ const exists = await Emoji.findOne({
+ host,
+ name
+ });
+
+ if (exists) {
+ return exists;
+ }
+
+ log(`register emoji host=${host}, name=${name}`);
+
+ return await Emoji.insert({
+ host,
+ name,
+ url: tag.icon.url,
+ aliases: [],
+ });
+ })
+ );
+}
diff --git a/src/remote/activitypub/models/tag.ts b/src/remote/activitypub/models/tag.ts
new file mode 100644
index 0000000000..5cdbfa43b1
--- /dev/null
+++ b/src/remote/activitypub/models/tag.ts
@@ -0,0 +1,12 @@
+import { IIcon } from "./icon";
+
+/***
+ * tag (ActivityPub)
+ */
+export type ITag = {
+ id: string;
+ type: string;
+ name?: string;
+ updated?: Date;
+ icon?: IIcon;
+};
diff --git a/src/remote/activitypub/renderer/emoji.ts b/src/remote/activitypub/renderer/emoji.ts
new file mode 100644
index 0000000000..b18337d274
--- /dev/null
+++ b/src/remote/activitypub/renderer/emoji.ts
@@ -0,0 +1,14 @@
+import { IEmoji } from '../../../models/emoji';
+import config from '../../../config';
+
+export default (emoji: IEmoji) => ({
+ id: `${config.url}/emojis/${emoji.name}`,
+ type: 'Emoji',
+ name: `:${emoji.name}:`,
+ updated: emoji.updatedAt != null ? emoji.updatedAt.toISOString() : new Date().toISOString,
+ icon: {
+ type: 'Image',
+ mediaType: 'image/png', //Mei-TODO
+ url: emoji.url
+ }
+});
diff --git a/src/remote/activitypub/renderer/note.ts b/src/remote/activitypub/renderer/note.ts
index b3ce1c03e4..a2c591de2e 100644
--- a/src/remote/activitypub/renderer/note.ts
+++ b/src/remote/activitypub/renderer/note.ts
@@ -1,12 +1,16 @@
import renderDocument from './document';
import renderHashtag from './hashtag';
import renderMention from './mention';
+import renderEmoji from './emoji';
import config from '../../../config';
import DriveFile, { IDriveFile } from '../../../models/drive-file';
import Note, { INote } from '../../../models/note';
import User from '../../../models/user';
import toHtml from '../misc/get-note-html';
import parseMfm from '../../../mfm/parse';
+import getEmojiNames from '../misc/get-emoji-names';
+import Emoji, { IEmoji } from '../../../models/emoji';
+import { unique } from '../../../prelude/array';
export default async function renderNote(note: INote, dive = true): Promise<any> {
const promisedFiles: Promise<IDriveFile[]> = note.fileIds
@@ -75,10 +79,6 @@ export default async function renderNote(note: INote, dive = true): Promise<any>
const hashtagTags = (note.tags || []).map(tag => renderHashtag(tag));
const mentionTags = mentionedUsers.map(u => renderMention(u));
- const tag = [
- ...hashtagTags,
- ...mentionTags,
- ];
const files = await promisedFiles;
@@ -108,12 +108,24 @@ export default async function renderNote(note: INote, dive = true): Promise<any>
}).join('');
}
+ const content = toHtml(Object.assign({}, note, { text }));
+
+ const emojiNames = unique(getEmojiNames(content));
+ const emojis = await getEmojis(emojiNames);
+ const apemojis = emojis.map(emoji => renderEmoji(emoji));
+
+ const tag = [
+ ...hashtagTags,
+ ...mentionTags,
+ ...apemojis,
+ ];
+
return {
id: `${config.url}/notes/${note._id}`,
type: 'Note',
attributedTo,
summary: note.cw,
- content: toHtml(Object.assign({}, note, { text })),
+ content,
_misskey_content: text,
published: note.createdAt.toISOString(),
to,
@@ -124,3 +136,18 @@ export default async function renderNote(note: INote, dive = true): Promise<any>
tag
};
}
+
+async function getEmojis(names: string[]): Promise<IEmoji[]> {
+ if (names == null || names.length < 1) return [];
+
+ const emojis = await Promise.all(
+ names.map(async name => {
+ return await Emoji.findOne({
+ name,
+ host: null
+ });
+ })
+ );
+
+ return emojis.filter(emoji => emoji != null);
+}