parent
							
								
									c48cbd95f6
								
							
						
					
					
						commit
						80b5fda292
					
				
					 18 changed files with 193 additions and 24 deletions
				
			
		| 
						 | 
					@ -24,6 +24,9 @@ export default Vue.component('misskey-flavored-markdown', {
 | 
				
			||||||
		i: {
 | 
							i: {
 | 
				
			||||||
			type: Object,
 | 
								type: Object,
 | 
				
			||||||
			default: null
 | 
								default: null
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							customEmojis: {
 | 
				
			||||||
 | 
								required: false,
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -186,17 +189,18 @@ export default Vue.component('misskey-flavored-markdown', {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				case 'emoji': {
 | 
									case 'emoji': {
 | 
				
			||||||
					//#region カスタム絵文字
 | 
										//#region カスタム絵文字
 | 
				
			||||||
					const customEmojis = (this.os.getMetaSync() || { emojis: [] }).emojis || [];
 | 
										if (this.customEmojis != null) {
 | 
				
			||||||
					const customEmoji = customEmojis.find(e => e.name == token.emoji || (e.aliases || []).includes(token.emoji));
 | 
											const customEmoji = this.customEmojis.find(e => e.name == token.emoji || (e.aliases || []).includes(token.emoji));
 | 
				
			||||||
					if (customEmoji) {
 | 
											if (customEmoji) {
 | 
				
			||||||
						return [createElement('img', {
 | 
												return [createElement('img', {
 | 
				
			||||||
							attrs: {
 | 
													attrs: {
 | 
				
			||||||
								src: customEmoji.url,
 | 
														src: customEmoji.url,
 | 
				
			||||||
								alt: token.emoji,
 | 
														alt: token.emoji,
 | 
				
			||||||
								title: token.emoji,
 | 
														title: token.emoji,
 | 
				
			||||||
								style: 'height: 2.5em; vertical-align: middle;'
 | 
														style: 'height: 2.5em; vertical-align: middle;'
 | 
				
			||||||
							}
 | 
													}
 | 
				
			||||||
						})];
 | 
												})];
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
					//#endregion
 | 
										//#endregion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -14,7 +14,7 @@
 | 
				
			||||||
					</div>
 | 
										</div>
 | 
				
			||||||
				</header>
 | 
									</header>
 | 
				
			||||||
				<div class="text">
 | 
									<div class="text">
 | 
				
			||||||
					<misskey-flavored-markdown v-if="note.text" :text="note.text"/>
 | 
										<misskey-flavored-markdown v-if="note.text" :text="note.text" :customEmojis="p.emojis"/>
 | 
				
			||||||
				</div>
 | 
									</div>
 | 
				
			||||||
			</div>
 | 
								</div>
 | 
				
			||||||
		</div>
 | 
							</div>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -45,7 +45,7 @@
 | 
				
			||||||
				<div class="text">
 | 
									<div class="text">
 | 
				
			||||||
					<span v-if="p.isHidden" style="opacity: 0.5">%i18n:@private%</span>
 | 
										<span v-if="p.isHidden" style="opacity: 0.5">%i18n:@private%</span>
 | 
				
			||||||
					<span v-if="p.deletedAt" style="opacity: 0.5">%i18n:@deleted%</span>
 | 
										<span v-if="p.deletedAt" style="opacity: 0.5">%i18n:@deleted%</span>
 | 
				
			||||||
					<misskey-flavored-markdown v-if="p.text" :text="p.text" :i="$store.state.i"/>
 | 
										<misskey-flavored-markdown v-if="p.text" :text="p.text" :i="$store.state.i" :customEmojis="p.emojis" />
 | 
				
			||||||
				</div>
 | 
									</div>
 | 
				
			||||||
				<div class="files" v-if="p.files.length > 0">
 | 
									<div class="files" v-if="p.files.length > 0">
 | 
				
			||||||
					<mk-media-list :media-list="p.files" :raw="true"/>
 | 
										<mk-media-list :media-list="p.files" :raw="true"/>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -34,7 +34,7 @@
 | 
				
			||||||
					<div class="text">
 | 
										<div class="text">
 | 
				
			||||||
						<span v-if="appearNote.isHidden" style="opacity: 0.5">%i18n:@private%</span>
 | 
											<span v-if="appearNote.isHidden" style="opacity: 0.5">%i18n:@private%</span>
 | 
				
			||||||
						<a class="reply" v-if="appearNote.reply">%fa:reply%</a>
 | 
											<a class="reply" v-if="appearNote.reply">%fa:reply%</a>
 | 
				
			||||||
						<misskey-flavored-markdown v-if="appearNote.text" :text="appearNote.text" :i="$store.state.i" :class="$style.text"/>
 | 
											<misskey-flavored-markdown v-if="appearNote.text" :text="appearNote.text" :i="$store.state.i" :class="$style.text" :customEmojis="appearNote.emojis"/>
 | 
				
			||||||
						<a class="rp" v-if="appearNote.renote">RN:</a>
 | 
											<a class="rp" v-if="appearNote.renote">RN:</a>
 | 
				
			||||||
					</div>
 | 
										</div>
 | 
				
			||||||
					<div class="files" v-if="appearNote.files.length > 0">
 | 
										<div class="files" v-if="appearNote.files.length > 0">
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,7 +4,7 @@
 | 
				
			||||||
		<span v-if="note.isHidden" style="opacity: 0.5">%i18n:@private%</span>
 | 
							<span v-if="note.isHidden" style="opacity: 0.5">%i18n:@private%</span>
 | 
				
			||||||
		<span v-if="note.deletedAt" style="opacity: 0.5">%i18n:@deleted%</span>
 | 
							<span v-if="note.deletedAt" style="opacity: 0.5">%i18n:@deleted%</span>
 | 
				
			||||||
		<a class="reply" v-if="note.replyId">%fa:reply%</a>
 | 
							<a class="reply" v-if="note.replyId">%fa:reply%</a>
 | 
				
			||||||
		<misskey-flavored-markdown v-if="note.text" :text="note.text" :i="$store.state.i"/>
 | 
							<misskey-flavored-markdown v-if="note.text" :text="note.text" :i="$store.state.i" :customEmojis="note.emojis"/>
 | 
				
			||||||
		<a class="rp" v-if="note.renoteId" :href="`/notes/${note.renoteId}`">RN: ...</a>
 | 
							<a class="rp" v-if="note.renoteId" :href="`/notes/${note.renoteId}`">RN: ...</a>
 | 
				
			||||||
	</div>
 | 
						</div>
 | 
				
			||||||
	<details v-if="note.files.length > 0">
 | 
						<details v-if="note.files.length > 0">
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -43,7 +43,7 @@
 | 
				
			||||||
				<div class="text">
 | 
									<div class="text">
 | 
				
			||||||
					<span v-if="p.isHidden" style="opacity: 0.5">(%i18n:@private%)</span>
 | 
										<span v-if="p.isHidden" style="opacity: 0.5">(%i18n:@private%)</span>
 | 
				
			||||||
					<span v-if="p.deletedAt" style="opacity: 0.5">(%i18n:@deleted%)</span>
 | 
										<span v-if="p.deletedAt" style="opacity: 0.5">(%i18n:@deleted%)</span>
 | 
				
			||||||
					<misskey-flavored-markdown v-if="p.text" :text="p.text" :i="$store.state.i"/>
 | 
										<misskey-flavored-markdown v-if="p.text" :text="p.text" :i="$store.state.i" :customEmojis="p.emojis"/>
 | 
				
			||||||
				</div>
 | 
									</div>
 | 
				
			||||||
				<div class="files" v-if="p.files.length > 0">
 | 
									<div class="files" v-if="p.files.length > 0">
 | 
				
			||||||
					<mk-media-list :media-list="p.files" :raw="true"/>
 | 
										<mk-media-list :media-list="p.files" :raw="true"/>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -30,7 +30,7 @@
 | 
				
			||||||
					<div class="text">
 | 
										<div class="text">
 | 
				
			||||||
						<span v-if="appearNote.isHidden" style="opacity: 0.5">(%i18n:@private%)</span>
 | 
											<span v-if="appearNote.isHidden" style="opacity: 0.5">(%i18n:@private%)</span>
 | 
				
			||||||
						<a class="reply" v-if="appearNote.reply">%fa:reply%</a>
 | 
											<a class="reply" v-if="appearNote.reply">%fa:reply%</a>
 | 
				
			||||||
						<misskey-flavored-markdown v-if="appearNote.text" :text="appearNote.text" :i="$store.state.i" :class="$style.text"/>
 | 
											<misskey-flavored-markdown v-if="appearNote.text" :text="appearNote.text" :i="$store.state.i" :class="$style.text" :customEmojis="appearNote.emojis"/>
 | 
				
			||||||
						<a class="rp" v-if="appearNote.renote != null">RN:</a>
 | 
											<a class="rp" v-if="appearNote.renote != null">RN:</a>
 | 
				
			||||||
					</div>
 | 
										</div>
 | 
				
			||||||
					<div class="files" v-if="appearNote.files.length > 0">
 | 
										<div class="files" v-if="appearNote.files.length > 0">
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,7 +4,7 @@
 | 
				
			||||||
		<span v-if="note.isHidden" style="opacity: 0.5">(%i18n:@private%)</span>
 | 
							<span v-if="note.isHidden" style="opacity: 0.5">(%i18n:@private%)</span>
 | 
				
			||||||
		<span v-if="note.deletedAt" style="opacity: 0.5">(%i18n:@deleted%)</span>
 | 
							<span v-if="note.deletedAt" style="opacity: 0.5">(%i18n:@deleted%)</span>
 | 
				
			||||||
		<a class="reply" v-if="note.replyId">%fa:reply%</a>
 | 
							<a class="reply" v-if="note.replyId">%fa:reply%</a>
 | 
				
			||||||
		<misskey-flavored-markdown v-if="note.text" :text="note.text" :i="$store.state.i"/>
 | 
							<misskey-flavored-markdown v-if="note.text" :text="note.text" :i="$store.state.i" :customEmojis="note.emojis"/>
 | 
				
			||||||
		<a class="rp" v-if="note.renoteId">RN: ...</a>
 | 
							<a class="rp" v-if="note.renoteId">RN: ...</a>
 | 
				
			||||||
	</div>
 | 
						</div>
 | 
				
			||||||
	<details v-if="note.files.length > 0">
 | 
						<details v-if="note.files.length > 0">
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										22
									
								
								src/models/emoji.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								src/models/emoji.ts
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,22 @@
 | 
				
			||||||
 | 
					import db from '../db/mongodb';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const Emoji = db.get<IEmoji>('emoji');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Emoji.createIndex(['name', 'host'], { unique: true });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default Emoji;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export type IEmoji = {
 | 
				
			||||||
 | 
						name: string;
 | 
				
			||||||
 | 
						host: string;
 | 
				
			||||||
 | 
						url: string;
 | 
				
			||||||
 | 
						aliases?: string[];
 | 
				
			||||||
 | 
						updatedAt?: Date;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const packEmojis = async (
 | 
				
			||||||
 | 
						host: string,
 | 
				
			||||||
 | 
						// MeiTODO: filter
 | 
				
			||||||
 | 
					) => {
 | 
				
			||||||
 | 
						return await Emoji.find({ host });
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
| 
						 | 
					@ -12,6 +12,7 @@ import { packMany as packFileMany, IDriveFile } from './drive-file';
 | 
				
			||||||
import Favorite from './favorite';
 | 
					import Favorite from './favorite';
 | 
				
			||||||
import Following from './following';
 | 
					import Following from './following';
 | 
				
			||||||
import config from '../config';
 | 
					import config from '../config';
 | 
				
			||||||
 | 
					import { packEmojis } from './emoji';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const Note = db.get<INote>('notes');
 | 
					const Note = db.get<INote>('notes');
 | 
				
			||||||
Note.createIndex('uri', { sparse: true, unique: true });
 | 
					Note.createIndex('uri', { sparse: true, unique: true });
 | 
				
			||||||
| 
						 | 
					@ -228,6 +229,11 @@ export const pack = async (
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const id = _note._id;
 | 
						const id = _note._id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// _note._userを消す前か、_note.userを解決した後でないとホストがわからない
 | 
				
			||||||
 | 
						if (_note._user) {
 | 
				
			||||||
 | 
							_note.emojis = packEmojis(_note._user.host);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Rename _id to id
 | 
						// Rename _id to id
 | 
				
			||||||
	_note.id = _note._id;
 | 
						_note.id = _note._id;
 | 
				
			||||||
	delete _note._id;
 | 
						delete _note._id;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										6
									
								
								src/remote/activitypub/misc/get-emoji-names.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								src/remote/activitypub/misc/get-emoji-names.ts
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -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);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										5
									
								
								src/remote/activitypub/models/icon.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								src/remote/activitypub/models/icon.ts
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,5 @@
 | 
				
			||||||
 | 
					export type IIcon = {
 | 
				
			||||||
 | 
						type: string;
 | 
				
			||||||
 | 
						mediaType?: string;
 | 
				
			||||||
 | 
						url?: string;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
| 
						 | 
					@ -10,6 +10,9 @@ import { resolvePerson, updatePerson } from './person';
 | 
				
			||||||
import { resolveImage } from './image';
 | 
					import { resolveImage } from './image';
 | 
				
			||||||
import { IRemoteUser, IUser } from '../../../models/user';
 | 
					import { IRemoteUser, IUser } from '../../../models/user';
 | 
				
			||||||
import htmlToMFM from '../../../mfm/html-to-mfm';
 | 
					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');
 | 
					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);
 | 
						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) {
 | 
						if (actor.updatedAt == null || Date.now() - actor.updatedAt.getTime() > 1000 * 60 * 60 * 24) {
 | 
				
			||||||
		updatePerson(note.attributedTo);
 | 
							updatePerson(note.attributedTo);
 | 
				
			||||||
| 
						 | 
					@ -135,3 +142,35 @@ export async function resolveNote(value: string | IObject, resolver?: Resolver):
 | 
				
			||||||
	// 添付されてきたNote Objectは偽装されている可能性があるため、常にuriを指定してサーバーフェッチを行う。
 | 
						// 添付されてきたNote Objectは偽装されている可能性があるため、常にuriを指定してサーバーフェッチを行う。
 | 
				
			||||||
	return await createNote(uri, resolver);
 | 
						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: [],
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
						);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										12
									
								
								src/remote/activitypub/models/tag.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								src/remote/activitypub/models/tag.ts
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,12 @@
 | 
				
			||||||
 | 
					import { IIcon } from "./icon";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/***
 | 
				
			||||||
 | 
					 * tag (ActivityPub)
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export type ITag = {
 | 
				
			||||||
 | 
						id: string;
 | 
				
			||||||
 | 
						type: string;
 | 
				
			||||||
 | 
						name?: string;
 | 
				
			||||||
 | 
						updated?: Date;
 | 
				
			||||||
 | 
						icon?: IIcon;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
							
								
								
									
										14
									
								
								src/remote/activitypub/renderer/emoji.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								src/remote/activitypub/renderer/emoji.ts
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -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
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
| 
						 | 
					@ -1,12 +1,16 @@
 | 
				
			||||||
import renderDocument from './document';
 | 
					import renderDocument from './document';
 | 
				
			||||||
import renderHashtag from './hashtag';
 | 
					import renderHashtag from './hashtag';
 | 
				
			||||||
import renderMention from './mention';
 | 
					import renderMention from './mention';
 | 
				
			||||||
 | 
					import renderEmoji from './emoji';
 | 
				
			||||||
import config from '../../../config';
 | 
					import config from '../../../config';
 | 
				
			||||||
import DriveFile, { IDriveFile } from '../../../models/drive-file';
 | 
					import DriveFile, { IDriveFile } from '../../../models/drive-file';
 | 
				
			||||||
import Note, { INote } from '../../../models/note';
 | 
					import Note, { INote } from '../../../models/note';
 | 
				
			||||||
import User from '../../../models/user';
 | 
					import User from '../../../models/user';
 | 
				
			||||||
import toHtml from '../misc/get-note-html';
 | 
					import toHtml from '../misc/get-note-html';
 | 
				
			||||||
import parseMfm from '../../../mfm/parse';
 | 
					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> {
 | 
					export default async function renderNote(note: INote, dive = true): Promise<any> {
 | 
				
			||||||
	const promisedFiles: Promise<IDriveFile[]> = note.fileIds
 | 
						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 hashtagTags = (note.tags || []).map(tag => renderHashtag(tag));
 | 
				
			||||||
	const mentionTags = mentionedUsers.map(u => renderMention(u));
 | 
						const mentionTags = mentionedUsers.map(u => renderMention(u));
 | 
				
			||||||
	const tag = [
 | 
					 | 
				
			||||||
		...hashtagTags,
 | 
					 | 
				
			||||||
		...mentionTags,
 | 
					 | 
				
			||||||
	];
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const files = await promisedFiles;
 | 
						const files = await promisedFiles;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -108,12 +108,24 @@ export default async function renderNote(note: INote, dive = true): Promise<any>
 | 
				
			||||||
		}).join('');
 | 
							}).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 {
 | 
						return {
 | 
				
			||||||
		id: `${config.url}/notes/${note._id}`,
 | 
							id: `${config.url}/notes/${note._id}`,
 | 
				
			||||||
		type: 'Note',
 | 
							type: 'Note',
 | 
				
			||||||
		attributedTo,
 | 
							attributedTo,
 | 
				
			||||||
		summary: note.cw,
 | 
							summary: note.cw,
 | 
				
			||||||
		content: toHtml(Object.assign({}, note, { text })),
 | 
							content,
 | 
				
			||||||
		_misskey_content: text,
 | 
							_misskey_content: text,
 | 
				
			||||||
		published: note.createdAt.toISOString(),
 | 
							published: note.createdAt.toISOString(),
 | 
				
			||||||
		to,
 | 
							to,
 | 
				
			||||||
| 
						 | 
					@ -124,3 +136,18 @@ export default async function renderNote(note: INote, dive = true): Promise<any>
 | 
				
			||||||
		tag
 | 
							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);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,6 +2,7 @@ import * as os from 'os';
 | 
				
			||||||
import config from '../../../config';
 | 
					import config from '../../../config';
 | 
				
			||||||
import Meta from '../../../models/meta';
 | 
					import Meta from '../../../models/meta';
 | 
				
			||||||
import { ILocalUser } from '../../../models/user';
 | 
					import { ILocalUser } from '../../../models/user';
 | 
				
			||||||
 | 
					import Emoji from '../../../models/emoji';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const pkg = require('../../../../package.json');
 | 
					const pkg = require('../../../../package.json');
 | 
				
			||||||
const client = require('../../../../built/client/meta.json');
 | 
					const client = require('../../../../built/client/meta.json');
 | 
				
			||||||
| 
						 | 
					@ -22,6 +23,8 @@ export const meta = {
 | 
				
			||||||
export default (params: any, me: ILocalUser) => new Promise(async (res, rej) => {
 | 
					export default (params: any, me: ILocalUser) => new Promise(async (res, rej) => {
 | 
				
			||||||
	const meta: any = (await Meta.findOne()) || {};
 | 
						const meta: any = (await Meta.findOne()) || {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const emojis = await Emoji.find({ host: null });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	res({
 | 
						res({
 | 
				
			||||||
		maintainer: config.maintainer,
 | 
							maintainer: config.maintainer,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -50,7 +53,7 @@ export default (params: any, me: ILocalUser) => new Promise(async (res, rej) =>
 | 
				
			||||||
		hidedTags: (me && me.isAdmin) ? meta.hidedTags : undefined,
 | 
							hidedTags: (me && me.isAdmin) ? meta.hidedTags : undefined,
 | 
				
			||||||
		bannerUrl: meta.bannerUrl,
 | 
							bannerUrl: meta.bannerUrl,
 | 
				
			||||||
		maxNoteTextLength: config.maxNoteTextLength,
 | 
							maxNoteTextLength: config.maxNoteTextLength,
 | 
				
			||||||
		emojis: meta.emojis,
 | 
							emojis: emojis,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		features: {
 | 
							features: {
 | 
				
			||||||
			registration: !meta.disableRegistration,
 | 
								registration: !meta.disableRegistration,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										31
									
								
								src/tools/add-emoji.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								src/tools/add-emoji.ts
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,31 @@
 | 
				
			||||||
 | 
					import * as debug from 'debug';
 | 
				
			||||||
 | 
					import Emoji from "../models/emoji";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					debug.enable('*');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					async function main(name: string, url: string, alias?: string): Promise<any> {
 | 
				
			||||||
 | 
						const aliases = alias != null ? [ alias ] : [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						await Emoji.insert({
 | 
				
			||||||
 | 
							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 'require name';
 | 
				
			||||||
 | 
					if (!url) throw 'require url';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					main(name, url).then(() => {
 | 
				
			||||||
 | 
						console.log('success');
 | 
				
			||||||
 | 
						process.exit(0);
 | 
				
			||||||
 | 
					}).catch(e => {
 | 
				
			||||||
 | 
						console.warn(e);
 | 
				
			||||||
 | 
						process.exit(1);
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue