Resolve #2691
This commit is contained in:
		
							parent
							
								
									bb8139196e
								
							
						
					
					
						commit
						046976dffc
					
				|  | @ -2,8 +2,8 @@ | |||
| <div class="mk-timeline"> | ||||
| 	<header> | ||||
| 		<span :data-active="src == 'home'" @click="src = 'home'">%fa:home% %i18n:@home%</span> | ||||
| 		<span :data-active="src == 'local'" @click="src = 'local'">%fa:R comments% %i18n:@local%</span> | ||||
| 		<span :data-active="src == 'hybrid'" @click="src = 'hybrid'">%fa:share-alt% %i18n:@hybrid%</span> | ||||
| 		<span :data-active="src == 'local'" @click="src = 'local'" v-if="enableLocalTimeline">%fa:R comments% %i18n:@local%</span> | ||||
| 		<span :data-active="src == 'hybrid'" @click="src = 'hybrid'" v-if="enableLocalTimeline">%fa:share-alt% %i18n:@hybrid%</span> | ||||
| 		<span :data-active="src == 'global'" @click="src = 'global'">%fa:globe% %i18n:@global%</span> | ||||
| 		<span :data-active="src == 'list'" @click="src = 'list'" v-if="list">%fa:list% {{ list.title }}</span> | ||||
| 		<button @click="chooseList" title="%i18n:@list%">%fa:list%</button> | ||||
|  | @ -29,7 +29,8 @@ export default Vue.extend({ | |||
| 	data() { | ||||
| 		return { | ||||
| 			src: 'home', | ||||
| 			list: null | ||||
| 			list: null, | ||||
| 			enableLocalTimeline: false | ||||
| 		}; | ||||
| 	}, | ||||
| 
 | ||||
|  | @ -44,6 +45,10 @@ export default Vue.extend({ | |||
| 	}, | ||||
| 
 | ||||
| 	created() { | ||||
| 		(this as any).os.getMeta().then(meta => { | ||||
| 			this.enableLocalTimeline = !meta.disableLocalTimeline; | ||||
| 		}); | ||||
| 
 | ||||
| 		if (this.$store.state.device.tl) { | ||||
| 			this.src = this.$store.state.device.tl.src; | ||||
| 			if (this.src == 'list') { | ||||
|  |  | |||
|  | @ -1,22 +1,34 @@ | |||
| <template> | ||||
| <div class="obdskegsannmntldydackcpzezagxqfy mk-admin-card"> | ||||
| 	<header>%i18n:@dashboard%</header> | ||||
| 
 | ||||
| 	<div v-if="stats" class="stats"> | ||||
| 		<div><b>%fa:user% {{ stats.originalUsersCount | number }}</b><span>%i18n:@original-users%</span></div> | ||||
| 		<div><span>%fa:user% {{ stats.usersCount | number }}</span><span>%i18n:@all-users%</span></div> | ||||
| 		<div><b>%fa:pencil-alt% {{ stats.originalNotesCount | number }}</b><span>%i18n:@original-notes%</span></div> | ||||
| 		<div><span>%fa:pencil-alt% {{ stats.notesCount | number }}</span><span>%i18n:@all-notes%</span></div> | ||||
| 	</div> | ||||
| 
 | ||||
| 	<div class="cpu-memory"> | ||||
| 		<x-cpu-memory :connection="connection"/> | ||||
| 	</div> | ||||
| 	<div> | ||||
| 		<label> | ||||
| 			<input type="checkbox" v-model="disableRegistration" @change="updateMeta"> | ||||
| 			<span>disableRegistration</span> | ||||
| 		</label> | ||||
| 		<button class="ui" @click="invite">%i18n:@invite%</button> | ||||
| 		<p v-if="inviteCode">Code: <code>{{ inviteCode }}</code></p> | ||||
| 
 | ||||
| 	<div class="form"> | ||||
| 		<div> | ||||
| 			<label> | ||||
| 				<input type="checkbox" v-model="disableRegistration" @change="updateMeta"> | ||||
| 				<span>%i18n:@disableRegistration%</span> | ||||
| 			</label> | ||||
| 			<button class="ui" @click="invite">%i18n:@invite%</button> | ||||
| 			<p v-if="inviteCode">Code: <code>{{ inviteCode }}</code></p> | ||||
| 		</div> | ||||
| 
 | ||||
| 		<div> | ||||
| 			<label> | ||||
| 				<input type="checkbox" v-model="disableLocalTimeline" @change="updateMeta"> | ||||
| 				<span>%i18n:@disableLocalTimeline%</span> | ||||
| 			</label> | ||||
| 		</div> | ||||
| 	</div> | ||||
| </div> | ||||
| </template> | ||||
|  | @ -33,6 +45,7 @@ export default Vue.extend({ | |||
| 		return { | ||||
| 			stats: null, | ||||
| 			disableRegistration: false, | ||||
| 			disableLocalTimeline: false, | ||||
| 			inviteCode: null, | ||||
| 			connection: null, | ||||
| 			connectionId: null | ||||
|  | @ -44,6 +57,7 @@ export default Vue.extend({ | |||
| 
 | ||||
| 		(this as any).os.getMeta().then(meta => { | ||||
| 			this.disableRegistration = meta.disableRegistration; | ||||
| 			this.disableLocalTimeline = meta.disableLocalTimeline; | ||||
| 		}); | ||||
| 
 | ||||
| 		(this as any).api('stats').then(stats => { | ||||
|  | @ -61,7 +75,8 @@ export default Vue.extend({ | |||
| 		}, | ||||
| 		updateMeta() { | ||||
| 			(this as any).api('admin/update-meta', { | ||||
| 				disableRegistration: this.disableRegistration | ||||
| 				disableRegistration: this.disableRegistration, | ||||
| 				disableLocalTimeline: this.disableLocalTimeline | ||||
| 			}); | ||||
| 		} | ||||
| 	} | ||||
|  | @ -97,4 +112,8 @@ export default Vue.extend({ | |||
| 		border solid 1px #eee | ||||
| 		border-radius: 8px | ||||
| 
 | ||||
| 	> .form | ||||
| 		> div | ||||
| 			border-bottom solid 1px #eee | ||||
| 
 | ||||
| </style> | ||||
|  |  | |||
|  | @ -24,8 +24,8 @@ | |||
| 			<div class="body"> | ||||
| 				<div> | ||||
| 					<span :data-active="src == 'home'" @click="src = 'home'">%fa:home% %i18n:@home%</span> | ||||
| 					<span :data-active="src == 'local'" @click="src = 'local'">%fa:R comments% %i18n:@local%</span> | ||||
| 					<span :data-active="src == 'hybrid'" @click="src = 'hybrid'">%fa:share-alt% %i18n:@hybrid%</span> | ||||
| 					<span :data-active="src == 'local'" @click="src = 'local'" v-if="enableLocalTimeline">%fa:R comments% %i18n:@local%</span> | ||||
| 					<span :data-active="src == 'hybrid'" @click="src = 'hybrid'" v-if="enableLocalTimeline">%fa:share-alt% %i18n:@hybrid%</span> | ||||
| 					<span :data-active="src == 'global'" @click="src = 'global'">%fa:globe% %i18n:@global%</span> | ||||
| 					<template v-if="lists"> | ||||
| 						<span v-for="l in lists" :data-active="src == 'list' && list == l" @click="src = 'list'; list = l" :key="l.id">%fa:list% {{ l.title }}</span> | ||||
|  | @ -60,7 +60,8 @@ export default Vue.extend({ | |||
| 			src: 'home', | ||||
| 			list: null, | ||||
| 			lists: null, | ||||
| 			showNav: false | ||||
| 			showNav: false, | ||||
| 			enableLocalTimeline: false | ||||
| 		}; | ||||
| 	}, | ||||
| 
 | ||||
|  | @ -85,6 +86,10 @@ export default Vue.extend({ | |||
| 	}, | ||||
| 
 | ||||
| 	created() { | ||||
| 		(this as any).os.getMeta().then(meta => { | ||||
| 			this.enableLocalTimeline = !meta.disableLocalTimeline; | ||||
| 		}); | ||||
| 
 | ||||
| 		if (this.$store.state.device.tl) { | ||||
| 			this.src = this.$store.state.device.tl.src; | ||||
| 			if (this.src == 'list') { | ||||
|  |  | |||
|  | @ -12,5 +12,6 @@ export type IMeta = { | |||
| 		originalUsersCount: number; | ||||
| 	}; | ||||
| 	disableRegistration?: boolean; | ||||
| 	disableLocalTimeline?: boolean; | ||||
| 	hidedTags?: string[]; | ||||
| }; | ||||
|  |  | |||
|  | @ -23,6 +23,12 @@ export const meta = { | |||
| 			} | ||||
| 		}), | ||||
| 
 | ||||
| 		disableLocalTimeline: $.bool.optional.nullable.note({ | ||||
| 			desc: { | ||||
| 				'ja-JP': 'ローカルタイムライン(とソーシャルタイムライン)を無効にするか否か' | ||||
| 			} | ||||
| 		}), | ||||
| 
 | ||||
| 		hidedTags: $.arr($.str).optional.nullable.note({ | ||||
| 			desc: { | ||||
| 				'ja-JP': '統計などで無視するハッシュタグ' | ||||
|  | @ -45,6 +51,10 @@ export default (params: any) => new Promise(async (res, rej) => { | |||
| 		set.disableRegistration = ps.disableRegistration; | ||||
| 	} | ||||
| 
 | ||||
| 	if (typeof ps.disableLocalTimeline === 'boolean') { | ||||
| 		set.disableLocalTimeline = ps.disableLocalTimeline; | ||||
| 	} | ||||
| 
 | ||||
| 	if (Array.isArray(ps.hidedTags)) { | ||||
| 		set.hidedTags = ps.hidedTags; | ||||
| 	} | ||||
|  |  | |||
|  | @ -34,6 +34,7 @@ export default (params: any, me: ILocalUser) => new Promise(async (res, rej) => | |||
| 		}, | ||||
| 		broadcasts: meta.broadcasts, | ||||
| 		disableRegistration: meta.disableRegistration, | ||||
| 		disableLocalTimeline: meta.disableLocalTimeline, | ||||
| 		driveCapacityPerLocalUserMb: config.localDriveCapacityMb, | ||||
| 		recaptchaSitekey: config.recaptcha ? config.recaptcha.site_key : null, | ||||
| 		swPublickey: config.sw ? config.sw.public_key : null, | ||||
|  |  | |||
							
								
								
									
										135
									
								
								src/stream.ts
								
								
								
								
							
							
						
						
									
										135
									
								
								src/stream.ts
								
								
								
								
							|  | @ -1,58 +1,97 @@ | |||
| import * as mongo from 'mongodb'; | ||||
| import Xev from 'xev'; | ||||
| 
 | ||||
| const ev = new Xev(); | ||||
| import Meta, { IMeta } from './models/meta'; | ||||
| 
 | ||||
| type ID = string | mongo.ObjectID; | ||||
| 
 | ||||
| function publish(channel: string, type: string, value?: any): void { | ||||
| 	const message = type == null ? value : value == null ? | ||||
| 		{ type: type } : | ||||
| 		{ type: type, body: value }; | ||||
| class Publisher { | ||||
| 	private ev: Xev; | ||||
| 	private meta: IMeta; | ||||
| 
 | ||||
| 	ev.emit(channel, message); | ||||
| 	constructor() { | ||||
| 		this.ev = new Xev(); | ||||
| 
 | ||||
| 		setInterval(async () => { | ||||
| 			this.meta = await Meta.findOne({}); | ||||
| 		}, 5000); | ||||
| 	} | ||||
| 
 | ||||
| 	public getMeta = async () => { | ||||
| 		if (this.meta != null) return this.meta; | ||||
| 
 | ||||
| 		this.meta = await Meta.findOne({}); | ||||
| 		return this.meta; | ||||
| 	} | ||||
| 
 | ||||
| 	private publish = (channel: string, type: string, value?: any): void => { | ||||
| 		const message = type == null ? value : value == null ? | ||||
| 			{ type: type } : | ||||
| 			{ type: type, body: value }; | ||||
| 
 | ||||
| 		this.ev.emit(channel, message); | ||||
| 	} | ||||
| 
 | ||||
| 	public publishUserStream = (userId: ID, type: string, value?: any): void => { | ||||
| 		this.publish(`user-stream:${userId}`, type, typeof value === 'undefined' ? null : value); | ||||
| 	} | ||||
| 
 | ||||
| 	public publishDriveStream = (userId: ID, type: string, value?: any): void => { | ||||
| 		this.publish(`drive-stream:${userId}`, type, typeof value === 'undefined' ? null : value); | ||||
| 	} | ||||
| 
 | ||||
| 	public publishNoteStream = (noteId: ID, type: string): void => { | ||||
| 		this.publish(`note-stream:${noteId}`, null, noteId); | ||||
| 	} | ||||
| 
 | ||||
| 	public publishUserListStream = (listId: ID, type: string, value?: any): void => { | ||||
| 		this.publish(`user-list-stream:${listId}`, type, typeof value === 'undefined' ? null : value); | ||||
| 	} | ||||
| 
 | ||||
| 	public publishMessagingStream = (userId: ID, otherpartyId: ID, type: string, value?: any): void => { | ||||
| 		this.publish(`messaging-stream:${userId}-${otherpartyId}`, type, typeof value === 'undefined' ? null : value); | ||||
| 	} | ||||
| 
 | ||||
| 	public publishMessagingIndexStream = (userId: ID, type: string, value?: any): void => { | ||||
| 		this.publish(`messaging-index-stream:${userId}`, type, typeof value === 'undefined' ? null : value); | ||||
| 	} | ||||
| 
 | ||||
| 	public publishReversiStream = (userId: ID, type: string, value?: any): void => { | ||||
| 		this.publish(`reversi-stream:${userId}`, type, typeof value === 'undefined' ? null : value); | ||||
| 	} | ||||
| 
 | ||||
| 	public publishReversiGameStream = (gameId: ID, type: string, value?: any): void => { | ||||
| 		this.publish(`reversi-game-stream:${gameId}`, type, typeof value === 'undefined' ? null : value); | ||||
| 	} | ||||
| 
 | ||||
| 	public publishLocalTimelineStream = async (note: any): Promise<void> => { | ||||
| 		const meta = await this.getMeta(); | ||||
| 		if (meta.disableLocalTimeline) return; | ||||
| 		this.publish('local-timeline', null, note); | ||||
| 	} | ||||
| 
 | ||||
| 	public publishHybridTimelineStream = async (userId: ID, note: any): Promise<void> => { | ||||
| 		const meta = await this.getMeta(); | ||||
| 		if (meta.disableLocalTimeline) return; | ||||
| 		this.publish(userId ? `hybrid-timeline:${userId}` : 'hybrid-timeline', null, note); | ||||
| 	} | ||||
| 
 | ||||
| 	public publishGlobalTimelineStream = (note: any): void => { | ||||
| 		this.publish('global-timeline', null, note); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| export function publishUserStream(userId: ID, type: string, value?: any): void { | ||||
| 	publish(`user-stream:${userId}`, type, typeof value === 'undefined' ? null : value); | ||||
| } | ||||
| const publisher = new Publisher(); | ||||
| 
 | ||||
| export function publishDriveStream(userId: ID, type: string, value?: any): void { | ||||
| 	publish(`drive-stream:${userId}`, type, typeof value === 'undefined' ? null : value); | ||||
| } | ||||
| export default publisher; | ||||
| 
 | ||||
| export function publishNoteStream(noteId: ID, type: string): void { | ||||
| 	publish(`note-stream:${noteId}`, null, noteId); | ||||
| } | ||||
| 
 | ||||
| export function publishUserListStream(listId: ID, type: string, value?: any): void { | ||||
| 	publish(`user-list-stream:${listId}`, type, typeof value === 'undefined' ? null : value); | ||||
| } | ||||
| 
 | ||||
| export function publishMessagingStream(userId: ID, otherpartyId: ID, type: string, value?: any): void { | ||||
| 	publish(`messaging-stream:${userId}-${otherpartyId}`, type, typeof value === 'undefined' ? null : value); | ||||
| } | ||||
| 
 | ||||
| export function publishMessagingIndexStream(userId: ID, type: string, value?: any): void { | ||||
| 	publish(`messaging-index-stream:${userId}`, type, typeof value === 'undefined' ? null : value); | ||||
| } | ||||
| 
 | ||||
| export function publishReversiStream(userId: ID, type: string, value?: any): void { | ||||
| 	publish(`reversi-stream:${userId}`, type, typeof value === 'undefined' ? null : value); | ||||
| } | ||||
| 
 | ||||
| export function publishReversiGameStream(gameId: ID, type: string, value?: any): void { | ||||
| 	publish(`reversi-game-stream:${gameId}`, type, typeof value === 'undefined' ? null : value); | ||||
| } | ||||
| 
 | ||||
| export function publishLocalTimelineStream(note: any): void { | ||||
| 	publish('local-timeline', null, note); | ||||
| } | ||||
| 
 | ||||
| export function publishHybridTimelineStream(userId: ID, note: any): void { | ||||
| 	publish(userId ? `hybrid-timeline:${userId}` : 'hybrid-timeline', null, note); | ||||
| } | ||||
| 
 | ||||
| export function publishGlobalTimelineStream(note: any): void { | ||||
| 	publish('global-timeline', null, note); | ||||
| } | ||||
| export const publishUserStream = publisher.publishUserStream; | ||||
| export const publishDriveStream = publisher.publishDriveStream; | ||||
| export const publishNoteStream = publisher.publishNoteStream; | ||||
| export const publishUserListStream = publisher.publishUserListStream; | ||||
| export const publishMessagingStream = publisher.publishMessagingStream; | ||||
| export const publishMessagingIndexStream = publisher.publishMessagingIndexStream; | ||||
| export const publishReversiStream = publisher.publishReversiStream; | ||||
| export const publishReversiGameStream = publisher.publishReversiGameStream; | ||||
| export const publishLocalTimelineStream = publisher.publishLocalTimelineStream; | ||||
| export const publishHybridTimelineStream = publisher.publishHybridTimelineStream; | ||||
| export const publishGlobalTimelineStream = publisher.publishGlobalTimelineStream; | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue