| @@ -1,21 +1,33 @@ | ||||
| import { publishMainStream } from '../../../services/stream'; | ||||
| import { publishMainStream, publishGroupMessagingStream } from '../../../services/stream'; | ||||
| import { publishMessagingStream } from '../../../services/stream'; | ||||
| import { publishMessagingIndexStream } from '../../../services/stream'; | ||||
| import { User } from '../../../models/entities/user'; | ||||
| import { MessagingMessage } from '../../../models/entities/messaging-message'; | ||||
| import { MessagingMessages } from '../../../models'; | ||||
| import { MessagingMessages, UserGroupJoinings, Users } from '../../../models'; | ||||
| import { In } from 'typeorm'; | ||||
| import { IdentifiableError } from '../../../misc/identifiable-error'; | ||||
| import { UserGroup } from '../../../models/entities/user-group'; | ||||
|  | ||||
| /** | ||||
|  * Mark messages as read | ||||
|  */ | ||||
| export default async ( | ||||
| export async function readUserMessagingMessage( | ||||
| 	userId: User['id'], | ||||
| 	otherpartyId: User['id'], | ||||
| 	messageIds: MessagingMessage['id'][] | ||||
| ) => { | ||||
| ) { | ||||
| 	if (messageIds.length === 0) return; | ||||
|  | ||||
| 	const messages = await MessagingMessages.find({ | ||||
| 		id: In(messageIds) | ||||
| 	}); | ||||
|  | ||||
| 	for (const message of messages) { | ||||
| 		if (message.recipientId !== userId) { | ||||
| 			throw new IdentifiableError('e140a4bf-49ce-4fb6-b67c-b78dadf6b52f', 'Access denied (user).'); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// Update documents | ||||
| 	await MessagingMessages.update({ | ||||
| 		id: In(messageIds), | ||||
| @@ -30,14 +42,62 @@ export default async ( | ||||
| 	publishMessagingStream(otherpartyId, userId, 'read', messageIds); | ||||
| 	publishMessagingIndexStream(userId, 'read', messageIds); | ||||
|  | ||||
| 	// Calc count of my unread messages | ||||
| 	const count = await MessagingMessages.count({ | ||||
| 		recipientId: userId, | ||||
| 		isRead: false | ||||
| 	}); | ||||
|  | ||||
| 	if (count == 0) { | ||||
| 	if (!Users.getHasUnreadMessagingMessage(userId)) { | ||||
| 		// 全ての(いままで未読だった)自分宛てのメッセージを(これで)読みましたよというイベントを発行 | ||||
| 		publishMainStream(userId, 'readAllMessagingMessages'); | ||||
| 	} | ||||
| }; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Mark messages as read | ||||
|  */ | ||||
| export async function readGroupMessagingMessage( | ||||
| 	userId: User['id'], | ||||
| 	groupId: UserGroup['id'], | ||||
| 	messageIds: MessagingMessage['id'][] | ||||
| ) { | ||||
| 	if (messageIds.length === 0) return; | ||||
|  | ||||
| 	// check joined | ||||
| 	const joining = await UserGroupJoinings.findOne({ | ||||
| 		userId: userId, | ||||
| 		userGroupId: groupId | ||||
| 	}); | ||||
|  | ||||
| 	if (joining == null) { | ||||
| 		throw new IdentifiableError('930a270c-714a-46b2-b776-ad27276dc569', 'Access denied (group).'); | ||||
| 	} | ||||
|  | ||||
| 	const messages = await MessagingMessages.find({ | ||||
| 		id: In(messageIds) | ||||
| 	}); | ||||
|  | ||||
| 	const reads = []; | ||||
|  | ||||
| 	for (const message of messages) { | ||||
| 		if (message.userId === userId) continue; | ||||
| 		if (message.reads.includes(userId)) continue; | ||||
|  | ||||
| 		// Update document | ||||
| 		await MessagingMessages.createQueryBuilder().update() | ||||
| 			.set({ | ||||
| 				reads: (() => `array_append("reads", '${joining.userId}')`) as any | ||||
| 			}) | ||||
| 			.where('id = :id', { id: message.id }) | ||||
| 			.execute(); | ||||
|  | ||||
| 		reads.push(message.id); | ||||
| 	} | ||||
|  | ||||
| 	// Publish event | ||||
| 	publishGroupMessagingStream(groupId, 'read', { | ||||
| 		ids: reads, | ||||
| 		userId: userId | ||||
| 	}); | ||||
| 	publishMessagingIndexStream(userId, 'read', reads); | ||||
|  | ||||
| 	if (!Users.getHasUnreadMessagingMessage(userId)) { | ||||
| 		// 全ての(いままで未読だった)自分宛てのメッセージを(これで)読みましたよというイベントを発行 | ||||
| 		publishMainStream(userId, 'readAllMessagingMessages'); | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -1,13 +1,13 @@ | ||||
| import $ from 'cafy'; | ||||
| import define from '../../define'; | ||||
| import { MessagingMessage } from '../../../../models/entities/messaging-message'; | ||||
| import { MessagingMessages, Mutings } from '../../../../models'; | ||||
| import { MessagingMessages, Mutings, UserGroupJoinings } from '../../../../models'; | ||||
| import { Brackets } from 'typeorm'; | ||||
| import { types, bool } from '../../../../misc/schema'; | ||||
|  | ||||
| export const meta = { | ||||
| 	desc: { | ||||
| 		'ja-JP': 'Messagingの履歴を取得します。', | ||||
| 		'ja-JP': 'トークの履歴を取得します。', | ||||
| 		'en-US': 'Show messaging history.' | ||||
| 	}, | ||||
|  | ||||
| @@ -21,6 +21,11 @@ export const meta = { | ||||
| 		limit: { | ||||
| 			validator: $.optional.num.range(1, 100), | ||||
| 			default: 10 | ||||
| 		}, | ||||
|  | ||||
| 		group: { | ||||
| 			validator: $.optional.bool, | ||||
| 			default: false | ||||
| 		} | ||||
| 	}, | ||||
|  | ||||
| @@ -40,26 +45,46 @@ export default define(meta, async (ps, user) => { | ||||
| 		muterId: user.id, | ||||
| 	}); | ||||
|  | ||||
| 	const groups = ps.group ? await UserGroupJoinings.find({ | ||||
| 		userId: user.id, | ||||
| 	}).then(xs => xs.map(x => x.userGroupId)) : []; | ||||
|  | ||||
| 	if (ps.group && groups.length === 0) { | ||||
| 		return []; | ||||
| 	} | ||||
|  | ||||
| 	const history: MessagingMessage[] = []; | ||||
|  | ||||
| 	for (let i = 0; i < ps.limit!; i++) { | ||||
| 		const found = history.map(m => (m.userId === user.id) ? m.recipientId : m.userId); | ||||
| 		const found = ps.group | ||||
| 			? history.map(m => m.groupId!) | ||||
| 			: history.map(m => (m.userId === user.id) ? m.recipientId! : m.userId!); | ||||
|  | ||||
| 		const query = MessagingMessages.createQueryBuilder('message') | ||||
| 			.where(new Brackets(qb => { qb | ||||
| 				.where(`message.userId = :userId`, { userId: user.id }) | ||||
| 				.orWhere(`message.recipientId = :userId`, { userId: user.id }); | ||||
| 			})) | ||||
| 			.orderBy('message.createdAt', 'DESC'); | ||||
|  | ||||
| 		if (found.length > 0) { | ||||
| 			query.andWhere(`message.userId NOT IN (:...found)`, { found: found }); | ||||
| 			query.andWhere(`message.recipientId NOT IN (:...found)`, { found: found }); | ||||
| 		} | ||||
| 		if (ps.group) { | ||||
| 			query.where(`message.groupId IN (:...groups)`, { groups: groups }); | ||||
|  | ||||
| 		if (mute.length > 0) { | ||||
| 			query.andWhere(`message.userId NOT IN (:...mute)`, { mute: mute.map(m => m.muteeId) }); | ||||
| 			query.andWhere(`message.recipientId NOT IN (:...mute)`, { mute: mute.map(m => m.muteeId) }); | ||||
| 			if (found.length > 0) { | ||||
| 				query.andWhere(`message.groupId NOT IN (:...found)`, { found: found }); | ||||
| 			} | ||||
| 		} else { | ||||
| 			query.where(new Brackets(qb => { qb | ||||
| 				.where(`message.userId = :userId`, { userId: user.id }) | ||||
| 				.orWhere(`message.recipientId = :userId`, { userId: user.id }); | ||||
| 			})); | ||||
| 			query.andWhere(`message.groupId IS NULL`); | ||||
|  | ||||
| 			if (found.length > 0) { | ||||
| 				query.andWhere(`message.userId NOT IN (:...found)`, { found: found }); | ||||
| 				query.andWhere(`message.recipientId NOT IN (:...found)`, { found: found }); | ||||
| 			} | ||||
|  | ||||
| 			if (mute.length > 0) { | ||||
| 				query.andWhere(`message.userId NOT IN (:...mute)`, { mute: mute.map(m => m.muteeId) }); | ||||
| 				query.andWhere(`message.recipientId NOT IN (:...mute)`, { mute: mute.map(m => m.muteeId) }); | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		const message = await query.getOne(); | ||||
|   | ||||
| @@ -1,16 +1,17 @@ | ||||
| import $ from 'cafy'; | ||||
| import { ID } from '../../../../misc/cafy-id'; | ||||
| import read from '../../common/read-messaging-message'; | ||||
| import define from '../../define'; | ||||
| import { ApiError } from '../../error'; | ||||
| import { getUser } from '../../common/getters'; | ||||
| import { MessagingMessages } from '../../../../models'; | ||||
| import { MessagingMessages, UserGroups, UserGroupJoinings } from '../../../../models'; | ||||
| import { makePaginationQuery } from '../../common/make-pagination-query'; | ||||
| import { types, bool } from '../../../../misc/schema'; | ||||
| import { Brackets } from 'typeorm'; | ||||
| import { readUserMessagingMessage, readGroupMessagingMessage } from '../../common/read-messaging-message'; | ||||
|  | ||||
| export const meta = { | ||||
| 	desc: { | ||||
| 		'ja-JP': '指定したユーザーとのMessagingのメッセージ一覧を取得します。', | ||||
| 		'ja-JP': 'トークメッセージ一覧を取得します。', | ||||
| 		'en-US': 'Get messages of messaging.' | ||||
| 	}, | ||||
|  | ||||
| @@ -22,13 +23,21 @@ export const meta = { | ||||
|  | ||||
| 	params: { | ||||
| 		userId: { | ||||
| 			validator: $.type(ID), | ||||
| 			validator: $.optional.type(ID), | ||||
| 			desc: { | ||||
| 				'ja-JP': '対象のユーザーのID', | ||||
| 				'en-US': 'Target user ID' | ||||
| 			} | ||||
| 		}, | ||||
|  | ||||
| 		groupId: { | ||||
| 			validator: $.optional.type(ID), | ||||
| 			desc: { | ||||
| 				'ja-JP': '対象のグループのID', | ||||
| 				'en-US': 'Target group ID' | ||||
| 			} | ||||
| 		}, | ||||
|  | ||||
| 		limit: { | ||||
| 			validator: $.optional.num.range(1, 100), | ||||
| 			default: 10 | ||||
| @@ -64,27 +73,85 @@ export const meta = { | ||||
| 			code: 'NO_SUCH_USER', | ||||
| 			id: '11795c64-40ea-4198-b06e-3c873ed9039d' | ||||
| 		}, | ||||
|  | ||||
| 		noSuchGroup: { | ||||
| 			message: 'No such group.', | ||||
| 			code: 'NO_SUCH_GROUP', | ||||
| 			id: 'c4d9f88c-9270-4632-b032-6ed8cee36f7f' | ||||
| 		}, | ||||
|  | ||||
| 		groupAccessDenied: { | ||||
| 			message: 'You can not read messages of groups that you have not joined.', | ||||
| 			code: 'GROUP_ACCESS_DENIED', | ||||
| 			id: 'a053a8dd-a491-4718-8f87-50775aad9284' | ||||
| 		}, | ||||
| 	} | ||||
| }; | ||||
|  | ||||
| export default define(meta, async (ps, user) => { | ||||
| 	// Fetch recipient | ||||
| 	const recipient = await getUser(ps.userId).catch(e => { | ||||
| 		if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError(meta.errors.noSuchUser); | ||||
| 		throw e; | ||||
| 	}); | ||||
| 	if (ps.userId != null) { | ||||
| 		// Fetch recipient (user) | ||||
| 		const recipient = await getUser(ps.userId).catch(e => { | ||||
| 			if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError(meta.errors.noSuchUser); | ||||
| 			throw e; | ||||
| 		}); | ||||
|  | ||||
| 	const query = makePaginationQuery(MessagingMessages.createQueryBuilder('message'), ps.sinceId, ps.untilId) | ||||
| 		.andWhere(`(message.userId = :meId AND message.recipientId = :recipientId) OR (message.userId = :recipientId AND message.recipientId = :meId)`, { meId: user.id, recipientId: recipient.id }); | ||||
| 		const query = makePaginationQuery(MessagingMessages.createQueryBuilder('message'), ps.sinceId, ps.untilId) | ||||
| 			.andWhere(new Brackets(qb => { qb | ||||
| 				.where(new Brackets(qb => { qb | ||||
| 					.where('message.userId = :meId') | ||||
| 					.andWhere('message.recipientId = :recipientId'); | ||||
| 				})) | ||||
| 				.orWhere(new Brackets(qb => { qb | ||||
| 					.where('message.userId = :recipientId') | ||||
| 					.andWhere('message.recipientId = :meId'); | ||||
| 				})); | ||||
| 			})) | ||||
| 			.setParameter('meId', user.id) | ||||
| 			.setParameter('recipientId', recipient.id); | ||||
|  | ||||
| 	const messages = await query.getMany(); | ||||
| 		const messages = await query.take(ps.limit!).getMany(); | ||||
|  | ||||
| 	// Mark all as read | ||||
| 	if (ps.markAsRead) { | ||||
| 		read(user.id, recipient.id, messages.map(x => x.id)); | ||||
| 		// Mark all as read | ||||
| 		if (ps.markAsRead) { | ||||
| 			readUserMessagingMessage(user.id, recipient.id, messages.map(x => x.id)); | ||||
| 		} | ||||
|  | ||||
| 		return await Promise.all(messages.map(message => MessagingMessages.pack(message, user, { | ||||
| 			populateRecipient: false | ||||
| 		}))); | ||||
| 	} else if (ps.groupId != null) { | ||||
| 		// Fetch recipient (group) | ||||
| 		const recipientGroup = await UserGroups.findOne(ps.groupId); | ||||
|  | ||||
| 		if (recipientGroup == null) { | ||||
| 			throw new ApiError(meta.errors.noSuchGroup); | ||||
| 		} | ||||
|  | ||||
| 		// check joined | ||||
| 		const joining = await UserGroupJoinings.findOne({ | ||||
| 			userId: user.id, | ||||
| 			userGroupId: recipientGroup.id | ||||
| 		}); | ||||
|  | ||||
| 		if (joining == null) { | ||||
| 			throw new ApiError(meta.errors.groupAccessDenied); | ||||
| 		} | ||||
|  | ||||
| 		const query = makePaginationQuery(MessagingMessages.createQueryBuilder('message'), ps.sinceId, ps.untilId) | ||||
| 			.andWhere(`message.groupId = :groupId`, { groupId: recipientGroup.id }); | ||||
|  | ||||
| 		const messages = await query.take(ps.limit!).getMany(); | ||||
|  | ||||
| 		// Mark all as read | ||||
| 		if (ps.markAsRead) { | ||||
| 			readGroupMessagingMessage(user.id, recipientGroup.id, messages.map(x => x.id)); | ||||
| 		} | ||||
|  | ||||
| 		return await Promise.all(messages.map(message => MessagingMessages.pack(message, user, { | ||||
| 			populateGroup: false | ||||
| 		}))); | ||||
| 	} else { | ||||
| 		throw new Error(); | ||||
| 	} | ||||
|  | ||||
| 	return await Promise.all(messages.map(message => MessagingMessages.pack(message, user, { | ||||
| 		populateRecipient: false | ||||
| 	}))); | ||||
| }); | ||||
|   | ||||
| @@ -1,19 +1,22 @@ | ||||
| import $ from 'cafy'; | ||||
| import { ID } from '../../../../../misc/cafy-id'; | ||||
| import { publishMainStream } from '../../../../../services/stream'; | ||||
| import { publishMainStream, publishGroupMessagingStream } from '../../../../../services/stream'; | ||||
| import { publishMessagingStream, publishMessagingIndexStream } from '../../../../../services/stream'; | ||||
| import pushSw from '../../../../../services/push-notification'; | ||||
| import define from '../../../define'; | ||||
| import { ApiError } from '../../../error'; | ||||
| import { getUser } from '../../../common/getters'; | ||||
| import { MessagingMessages, DriveFiles, Mutings } from '../../../../../models'; | ||||
| import { MessagingMessages, DriveFiles, Mutings, UserGroups, UserGroupJoinings } from '../../../../../models'; | ||||
| import { MessagingMessage } from '../../../../../models/entities/messaging-message'; | ||||
| import { genId } from '../../../../../misc/gen-id'; | ||||
| import { types, bool } from '../../../../../misc/schema'; | ||||
| import { User } from '../../../../../models/entities/user'; | ||||
| import { UserGroup } from '../../../../../models/entities/user-group'; | ||||
| import { Not } from 'typeorm'; | ||||
|  | ||||
| export const meta = { | ||||
| 	desc: { | ||||
| 		'ja-JP': '指定したユーザーへMessagingのメッセージを送信します。', | ||||
| 		'ja-JP': 'トークメッセージを送信します。', | ||||
| 		'en-US': 'Create a message of messaging.' | ||||
| 	}, | ||||
|  | ||||
| @@ -25,13 +28,21 @@ export const meta = { | ||||
|  | ||||
| 	params: { | ||||
| 		userId: { | ||||
| 			validator: $.type(ID), | ||||
| 			validator: $.optional.type(ID), | ||||
| 			desc: { | ||||
| 				'ja-JP': '対象のユーザーのID', | ||||
| 				'en-US': 'Target user ID' | ||||
| 			} | ||||
| 		}, | ||||
|  | ||||
| 		groupId: { | ||||
| 			validator: $.optional.type(ID), | ||||
| 			desc: { | ||||
| 				'ja-JP': '対象のグループのID', | ||||
| 				'en-US': 'Target group ID' | ||||
| 			} | ||||
| 		}, | ||||
|  | ||||
| 		text: { | ||||
| 			validator: $.optional.str.pipe(MessagingMessages.isValidText) | ||||
| 		}, | ||||
| @@ -60,6 +71,18 @@ export const meta = { | ||||
| 			id: '11795c64-40ea-4198-b06e-3c873ed9039d' | ||||
| 		}, | ||||
|  | ||||
| 		noSuchGroup: { | ||||
| 			message: 'No such group.', | ||||
| 			code: 'NO_SUCH_GROUP', | ||||
| 			id: 'c94e2a5d-06aa-4914-8fa6-6a42e73d6537' | ||||
| 		}, | ||||
|  | ||||
| 		groupAccessDenied: { | ||||
| 			message: 'You can not send messages to groups that you have not joined.', | ||||
| 			code: 'GROUP_ACCESS_DENIED', | ||||
| 			id: 'd96b3cca-5ad1-438b-ad8b-02f931308fbd' | ||||
| 		}, | ||||
|  | ||||
| 		noSuchFile: { | ||||
| 			message: 'No such file.', | ||||
| 			code: 'NO_SUCH_FILE', | ||||
| @@ -75,16 +98,38 @@ export const meta = { | ||||
| }; | ||||
|  | ||||
| export default define(meta, async (ps, user) => { | ||||
| 	// Myself | ||||
| 	if (ps.userId === user.id) { | ||||
| 		throw new ApiError(meta.errors.recipientIsYourself); | ||||
| 	} | ||||
| 	let recipientUser: User | undefined; | ||||
| 	let recipientGroup: UserGroup | undefined; | ||||
|  | ||||
| 	// Fetch recipient | ||||
| 	const recipient = await getUser(ps.userId).catch(e => { | ||||
| 		if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError(meta.errors.noSuchUser); | ||||
| 		throw e; | ||||
| 	}); | ||||
| 	if (ps.userId != null) { | ||||
| 		// Myself | ||||
| 		if (ps.userId === user.id) { | ||||
| 			throw new ApiError(meta.errors.recipientIsYourself); | ||||
| 		} | ||||
|  | ||||
| 		// Fetch recipient (user) | ||||
| 		recipientUser = await getUser(ps.userId).catch(e => { | ||||
| 			if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError(meta.errors.noSuchUser); | ||||
| 			throw e; | ||||
| 		}); | ||||
| 	} else if (ps.groupId != null) { | ||||
| 		// Fetch recipient (group) | ||||
| 		recipientGroup = await UserGroups.findOne(ps.groupId); | ||||
|  | ||||
| 		if (recipientGroup == null) { | ||||
| 			throw new ApiError(meta.errors.noSuchGroup); | ||||
| 		} | ||||
|  | ||||
| 		// check joined | ||||
| 		const joining = await UserGroupJoinings.findOne({ | ||||
| 			userId: user.id, | ||||
| 			userGroupId: recipientGroup.id | ||||
| 		}); | ||||
|  | ||||
| 		if (joining == null) { | ||||
| 			throw new ApiError(meta.errors.groupAccessDenied); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	let file = null; | ||||
| 	if (ps.fileId != null) { | ||||
| @@ -107,32 +152,49 @@ export default define(meta, async (ps, user) => { | ||||
| 		id: genId(), | ||||
| 		createdAt: new Date(), | ||||
| 		fileId: file ? file.id : null, | ||||
| 		recipientId: recipient.id, | ||||
| 		recipientId: recipientUser ? recipientUser.id : null, | ||||
| 		groupId: recipientGroup ? recipientGroup.id : null, | ||||
| 		text: ps.text ? ps.text.trim() : null, | ||||
| 		userId: user.id, | ||||
| 		isRead: false | ||||
| 		isRead: false, | ||||
| 		reads: [] as any[] | ||||
| 	} as MessagingMessage); | ||||
|  | ||||
| 	const messageObj = await MessagingMessages.pack(message); | ||||
|  | ||||
| 	// 自分のストリーム | ||||
| 	publishMessagingStream(message.userId, message.recipientId, 'message', messageObj); | ||||
| 	publishMessagingIndexStream(message.userId, 'message', messageObj); | ||||
| 	publishMainStream(message.userId, 'messagingMessage', messageObj); | ||||
| 	if (recipientUser) { | ||||
| 		// 自分のストリーム | ||||
| 		publishMessagingStream(message.userId, recipientUser.id, 'message', messageObj); | ||||
| 		publishMessagingIndexStream(message.userId, 'message', messageObj); | ||||
| 		publishMainStream(message.userId, 'messagingMessage', messageObj); | ||||
|  | ||||
| 	// 相手のストリーム | ||||
| 	publishMessagingStream(message.recipientId, message.userId, 'message', messageObj); | ||||
| 	publishMessagingIndexStream(message.recipientId, 'message', messageObj); | ||||
| 	publishMainStream(message.recipientId, 'messagingMessage', messageObj); | ||||
| 		// 相手のストリーム | ||||
| 		publishMessagingStream(recipientUser.id, message.userId, 'message', messageObj); | ||||
| 		publishMessagingIndexStream(recipientUser.id, 'message', messageObj); | ||||
| 		publishMainStream(recipientUser.id, 'messagingMessage', messageObj); | ||||
| 	} else if (recipientGroup) { | ||||
| 		// グループのストリーム | ||||
| 		publishGroupMessagingStream(recipientGroup.id, 'message', messageObj); | ||||
|  | ||||
| 		// メンバーのストリーム | ||||
| 		const joinings = await UserGroupJoinings.find({ userGroupId: recipientGroup.id }); | ||||
| 		for (const joining of joinings) { | ||||
| 			publishMessagingIndexStream(joining.userId, 'message', messageObj); | ||||
| 			publishMainStream(joining.userId, 'messagingMessage', messageObj); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// 2秒経っても(今回作成した)メッセージが既読にならなかったら「未読のメッセージがありますよ」イベントを発行する | ||||
| 	setTimeout(async () => { | ||||
| 		const freshMessage = await MessagingMessages.findOne({ id: message.id }); | ||||
| 		const freshMessage = await MessagingMessages.findOne(message.id); | ||||
| 		if (freshMessage == null) return; // メッセージが削除されている場合もある | ||||
| 		if (!freshMessage.isRead) { | ||||
|  | ||||
| 		if (recipientUser) { | ||||
| 			if (freshMessage.isRead) return; // 既読 | ||||
|  | ||||
| 			//#region ただしミュートされているなら発行しない | ||||
| 			const mute = await Mutings.find({ | ||||
| 				muterId: recipient.id, | ||||
| 				muterId: recipientUser.id, | ||||
| 			}); | ||||
| 			const mutedUserIds = mute.map(m => m.muteeId.toString()); | ||||
| 			if (mutedUserIds.indexOf(user.id) != -1) { | ||||
| @@ -140,8 +202,15 @@ export default define(meta, async (ps, user) => { | ||||
| 			} | ||||
| 			//#endregion | ||||
|  | ||||
| 			publishMainStream(message.recipientId, 'unreadMessagingMessage', messageObj); | ||||
| 			pushSw(message.recipientId, 'unreadMessagingMessage', messageObj); | ||||
| 			publishMainStream(recipientUser.id, 'unreadMessagingMessage', messageObj); | ||||
| 			pushSw(recipientUser.id, 'unreadMessagingMessage', messageObj); | ||||
| 		} else if (recipientGroup) { | ||||
| 			const joinings = await UserGroupJoinings.find({ userGroupId: recipientGroup.id, userId: Not(user.id) }); | ||||
| 			for (const joining of joinings) { | ||||
| 				if (freshMessage.reads.includes(joining.userId)) return; // 既読 | ||||
| 				publishMainStream(joining.userId, 'unreadMessagingMessage', messageObj); | ||||
| 				pushSw(joining.userId, 'unreadMessagingMessage', messageObj); | ||||
| 			} | ||||
| 		} | ||||
| 	}, 2000); | ||||
|  | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| import $ from 'cafy'; | ||||
| import { ID } from '../../../../../misc/cafy-id'; | ||||
| import define from '../../../define'; | ||||
| import { publishMessagingStream } from '../../../../../services/stream'; | ||||
| import { publishMessagingStream, publishGroupMessagingStream } from '../../../../../services/stream'; | ||||
| import * as ms from 'ms'; | ||||
| import { ApiError } from '../../../error'; | ||||
| import { MessagingMessages } from '../../../../../models'; | ||||
| @@ -10,7 +10,7 @@ export const meta = { | ||||
| 	stability: 'stable', | ||||
|  | ||||
| 	desc: { | ||||
| 		'ja-JP': '指定したメッセージを削除します。', | ||||
| 		'ja-JP': '指定したトークメッセージを削除します。', | ||||
| 		'en-US': 'Delete a message.' | ||||
| 	}, | ||||
|  | ||||
| @@ -57,6 +57,10 @@ export default define(meta, async (ps, user) => { | ||||
|  | ||||
| 	await MessagingMessages.delete(message.id); | ||||
|  | ||||
| 	publishMessagingStream(message.userId, message.recipientId, 'deleted', message.id); | ||||
| 	publishMessagingStream(message.recipientId, message.userId, 'deleted', message.id); | ||||
| 	if (message.recipientId) { | ||||
| 		publishMessagingStream(message.userId, message.recipientId, 'deleted', message.id); | ||||
| 		publishMessagingStream(message.recipientId, message.userId, 'deleted', message.id); | ||||
| 	} else if (message.groupId) { | ||||
| 		publishGroupMessagingStream(message.groupId, 'deleted', message.id); | ||||
| 	} | ||||
| }); | ||||
|   | ||||
| @@ -1,13 +1,13 @@ | ||||
| import $ from 'cafy'; | ||||
| import { ID } from '../../../../../misc/cafy-id'; | ||||
| import read from '../../../common/read-messaging-message'; | ||||
| import define from '../../../define'; | ||||
| import { ApiError } from '../../../error'; | ||||
| import { MessagingMessages } from '../../../../../models'; | ||||
| import { readUserMessagingMessage, readGroupMessagingMessage } from '../../../common/read-messaging-message'; | ||||
|  | ||||
| export const meta = { | ||||
| 	desc: { | ||||
| 		'ja-JP': '指定した自分宛てのメッセージを既読にします。', | ||||
| 		'ja-JP': '指定した自分宛てのトークメッセージを既読にします。', | ||||
| 		'en-US': 'Mark as read a message of messaging.' | ||||
| 	}, | ||||
|  | ||||
| @@ -39,12 +39,21 @@ export const meta = { | ||||
| export default define(meta, async (ps, user) => { | ||||
| 	const message = await MessagingMessages.findOne({ | ||||
| 		id: ps.messageId, | ||||
| 		recipientId: user.id | ||||
| 	}); | ||||
|  | ||||
| 	if (message == null) { | ||||
| 		throw new ApiError(meta.errors.noSuchMessage); | ||||
| 	} | ||||
|  | ||||
| 	read(user.id, message.userId, [message.id]); | ||||
| 	if (message.recipientId) { | ||||
| 		await readUserMessagingMessage(user.id, message.recipientId, [message.id]).catch(e => { | ||||
| 			if (e.id === 'e140a4bf-49ce-4fb6-b67c-b78dadf6b52f') throw new ApiError(meta.errors.noSuchMessage); | ||||
| 			throw e; | ||||
| 		}); | ||||
| 	} else if (message.groupId) { | ||||
| 		await readGroupMessagingMessage(user.id, message.groupId, [message.id]).catch(e => { | ||||
| 			if (e.id === '930a270c-714a-46b2-b776-ad27276dc569') throw new ApiError(meta.errors.noSuchMessage); | ||||
| 			throw e; | ||||
| 		}); | ||||
| 	} | ||||
| }); | ||||
|   | ||||
							
								
								
									
										51
									
								
								src/server/api/endpoints/users/groups/create.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								src/server/api/endpoints/users/groups/create.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,51 @@ | ||||
| import $ from 'cafy'; | ||||
| import define from '../../../define'; | ||||
| import { UserGroups, UserGroupJoinings } from '../../../../../models'; | ||||
| import { genId } from '../../../../../misc/gen-id'; | ||||
| import { UserGroup } from '../../../../../models/entities/user-group'; | ||||
| import { types, bool } from '../../../../../misc/schema'; | ||||
| import { UserGroupJoining } from '../../../../../models/entities/user-group-joining'; | ||||
|  | ||||
| export const meta = { | ||||
| 	desc: { | ||||
| 		'ja-JP': 'ユーザーグループを作成します。', | ||||
| 		'en-US': 'Create a user group.' | ||||
| 	}, | ||||
|  | ||||
| 	tags: ['groups'], | ||||
|  | ||||
| 	requireCredential: true, | ||||
|  | ||||
| 	kind: 'write:user-groups', | ||||
|  | ||||
| 	params: { | ||||
| 		name: { | ||||
| 			validator: $.str.range(1, 100) | ||||
| 		} | ||||
| 	}, | ||||
|  | ||||
| 	res: { | ||||
| 		type: types.object, | ||||
| 		optional: bool.false, nullable: bool.false, | ||||
| 		ref: 'UserGroup', | ||||
| 	}, | ||||
| }; | ||||
|  | ||||
| export default define(meta, async (ps, user) => { | ||||
| 	const userGroup = await UserGroups.save({ | ||||
| 		id: genId(), | ||||
| 		createdAt: new Date(), | ||||
| 		userId: user.id, | ||||
| 		name: ps.name, | ||||
| 	} as UserGroup); | ||||
|  | ||||
| 	// Push the owner | ||||
| 	await UserGroupJoinings.save({ | ||||
| 		id: genId(), | ||||
| 		createdAt: new Date(), | ||||
| 		userId: user.id, | ||||
| 		userGroupId: userGroup.id | ||||
| 	} as UserGroupJoining); | ||||
|  | ||||
| 	return await UserGroups.pack(userGroup); | ||||
| }); | ||||
							
								
								
									
										49
									
								
								src/server/api/endpoints/users/groups/delete.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								src/server/api/endpoints/users/groups/delete.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,49 @@ | ||||
| import $ from 'cafy'; | ||||
| import { ID } from '../../../../../misc/cafy-id'; | ||||
| import define from '../../../define'; | ||||
| import { ApiError } from '../../../error'; | ||||
| import { UserGroups } from '../../../../../models'; | ||||
|  | ||||
| export const meta = { | ||||
| 	desc: { | ||||
| 		'ja-JP': '指定したユーザーグループを削除します。', | ||||
| 		'en-US': 'Delete a user group' | ||||
| 	}, | ||||
|  | ||||
| 	tags: ['groups'], | ||||
|  | ||||
| 	requireCredential: true, | ||||
|  | ||||
| 	kind: 'write:user-groups', | ||||
|  | ||||
| 	params: { | ||||
| 		groupId: { | ||||
| 			validator: $.type(ID), | ||||
| 			desc: { | ||||
| 				'ja-JP': '対象となるユーザーグループのID', | ||||
| 				'en-US': 'ID of target user group' | ||||
| 			} | ||||
| 		} | ||||
| 	}, | ||||
|  | ||||
| 	errors: { | ||||
| 		noSuchGroup: { | ||||
| 			message: 'No such group.', | ||||
| 			code: 'NO_SUCH_GROUP', | ||||
| 			id: '63dbd64c-cd77-413f-8e08-61781e210b38' | ||||
| 		} | ||||
| 	} | ||||
| }; | ||||
|  | ||||
| export default define(meta, async (ps, user) => { | ||||
| 	const userGroup = await UserGroups.findOne({ | ||||
| 		id: ps.groupId, | ||||
| 		userId: user.id | ||||
| 	}); | ||||
|  | ||||
| 	if (userGroup == null) { | ||||
| 		throw new ApiError(meta.errors.noSuchGroup); | ||||
| 	} | ||||
|  | ||||
| 	await UserGroups.delete(userGroup.id); | ||||
| }); | ||||
							
								
								
									
										33
									
								
								src/server/api/endpoints/users/groups/joined.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								src/server/api/endpoints/users/groups/joined.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,33 @@ | ||||
| import define from '../../../define'; | ||||
| import { UserGroups, UserGroupJoinings } from '../../../../../models'; | ||||
| import { types, bool } from '../../../../../misc/schema'; | ||||
|  | ||||
| export const meta = { | ||||
| 	desc: { | ||||
| 		'ja-JP': '自分の所属するユーザーグループ一覧を取得します。' | ||||
| 	}, | ||||
|  | ||||
| 	tags: ['groups', 'account'], | ||||
|  | ||||
| 	requireCredential: true, | ||||
|  | ||||
| 	kind: 'read:user-groups', | ||||
|  | ||||
| 	res: { | ||||
| 		type: types.array, | ||||
| 		optional: bool.false, nullable: bool.false, | ||||
| 		items: { | ||||
| 			type: types.object, | ||||
| 			optional: bool.false, nullable: bool.false, | ||||
| 			ref: 'UserGroup', | ||||
| 		} | ||||
| 	}, | ||||
| }; | ||||
|  | ||||
| export default define(meta, async (ps, me) => { | ||||
| 	const joinings = await UserGroupJoinings.find({ | ||||
| 		userId: me.id, | ||||
| 	}); | ||||
|  | ||||
| 	return await Promise.all(joinings.map(x => UserGroups.pack(x.userGroupId))); | ||||
| }); | ||||
							
								
								
									
										33
									
								
								src/server/api/endpoints/users/groups/owned.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								src/server/api/endpoints/users/groups/owned.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,33 @@ | ||||
| import define from '../../../define'; | ||||
| import { UserGroups } from '../../../../../models'; | ||||
| import { types, bool } from '../../../../../misc/schema'; | ||||
|  | ||||
| export const meta = { | ||||
| 	desc: { | ||||
| 		'ja-JP': '自分の作成したユーザーグループ一覧を取得します。' | ||||
| 	}, | ||||
|  | ||||
| 	tags: ['groups', 'account'], | ||||
|  | ||||
| 	requireCredential: true, | ||||
|  | ||||
| 	kind: 'read:user-groups', | ||||
|  | ||||
| 	res: { | ||||
| 		type: types.array, | ||||
| 		optional: bool.false, nullable: bool.false, | ||||
| 		items: { | ||||
| 			type: types.object, | ||||
| 			optional: bool.false, nullable: bool.false, | ||||
| 			ref: 'UserGroup', | ||||
| 		} | ||||
| 	}, | ||||
| }; | ||||
|  | ||||
| export default define(meta, async (ps, me) => { | ||||
| 	const userGroups = await UserGroups.find({ | ||||
| 		userId: me.id, | ||||
| 	}); | ||||
|  | ||||
| 	return await Promise.all(userGroups.map(x => UserGroups.pack(x))); | ||||
| }); | ||||
							
								
								
									
										68
									
								
								src/server/api/endpoints/users/groups/pull.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								src/server/api/endpoints/users/groups/pull.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,68 @@ | ||||
| import $ from 'cafy'; | ||||
| import { ID } from '../../../../../misc/cafy-id'; | ||||
| import define from '../../../define'; | ||||
| import { ApiError } from '../../../error'; | ||||
| import { getUser } from '../../../common/getters'; | ||||
| import { UserGroups, UserGroupJoinings } from '../../../../../models'; | ||||
|  | ||||
| export const meta = { | ||||
| 	desc: { | ||||
| 		'ja-JP': '指定したユーザーグループから指定したユーザーを削除します。', | ||||
| 		'en-US': 'Remove a user to a user group.' | ||||
| 	}, | ||||
|  | ||||
| 	tags: ['groups', 'users'], | ||||
|  | ||||
| 	requireCredential: true, | ||||
|  | ||||
| 	kind: 'write:user-groups', | ||||
|  | ||||
| 	params: { | ||||
| 		groupId: { | ||||
| 			validator: $.type(ID), | ||||
| 		}, | ||||
|  | ||||
| 		userId: { | ||||
| 			validator: $.type(ID), | ||||
| 			desc: { | ||||
| 				'ja-JP': '対象のユーザーのID', | ||||
| 				'en-US': 'Target user ID' | ||||
| 			} | ||||
| 		}, | ||||
| 	}, | ||||
|  | ||||
| 	errors: { | ||||
| 		noSuchGroup: { | ||||
| 			message: 'No such group.', | ||||
| 			code: 'NO_SUCH_GROUP', | ||||
| 			id: '4662487c-05b1-4b78-86e5-fd46998aba74' | ||||
| 		}, | ||||
|  | ||||
| 		noSuchUser: { | ||||
| 			message: 'No such user.', | ||||
| 			code: 'NO_SUCH_USER', | ||||
| 			id: '0b5cc374-3681-41da-861e-8bc1146f7a55' | ||||
| 		} | ||||
| 	} | ||||
| }; | ||||
|  | ||||
| export default define(meta, async (ps, me) => { | ||||
| 	// Fetch the group | ||||
| 	const userGroup = await UserGroups.findOne({ | ||||
| 		id: ps.groupId, | ||||
| 		userId: me.id, | ||||
| 	}); | ||||
|  | ||||
| 	if (userGroup == null) { | ||||
| 		throw new ApiError(meta.errors.noSuchGroup); | ||||
| 	} | ||||
|  | ||||
| 	// Fetch the user | ||||
| 	const user = await getUser(ps.userId).catch(e => { | ||||
| 		if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError(meta.errors.noSuchUser); | ||||
| 		throw e; | ||||
| 	}); | ||||
|  | ||||
| 	// Pull the user | ||||
| 	await UserGroupJoinings.delete({ userId: user.id }); | ||||
| }); | ||||
							
								
								
									
										90
									
								
								src/server/api/endpoints/users/groups/push.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										90
									
								
								src/server/api/endpoints/users/groups/push.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,90 @@ | ||||
| import $ from 'cafy'; | ||||
| import { ID } from '../../../../../misc/cafy-id'; | ||||
| import define from '../../../define'; | ||||
| import { ApiError } from '../../../error'; | ||||
| import { getUser } from '../../../common/getters'; | ||||
| import { UserGroups, UserGroupJoinings } from '../../../../../models'; | ||||
| import { genId } from '../../../../../misc/gen-id'; | ||||
| import { UserGroupJoining } from '../../../../../models/entities/user-group-joining'; | ||||
|  | ||||
| export const meta = { | ||||
| 	desc: { | ||||
| 		'ja-JP': '指定したユーザーグループに指定したユーザーを追加します。', | ||||
| 		'en-US': 'Add a user to a user group.' | ||||
| 	}, | ||||
|  | ||||
| 	tags: ['groups', 'users'], | ||||
|  | ||||
| 	requireCredential: true, | ||||
|  | ||||
| 	kind: 'write:user-groups', | ||||
|  | ||||
| 	params: { | ||||
| 		groupId: { | ||||
| 			validator: $.type(ID), | ||||
| 		}, | ||||
|  | ||||
| 		userId: { | ||||
| 			validator: $.type(ID), | ||||
| 			desc: { | ||||
| 				'ja-JP': '対象のユーザーのID', | ||||
| 				'en-US': 'Target user ID' | ||||
| 			} | ||||
| 		}, | ||||
| 	}, | ||||
|  | ||||
| 	errors: { | ||||
| 		noSuchGroup: { | ||||
| 			message: 'No such group.', | ||||
| 			code: 'NO_SUCH_GROUP', | ||||
| 			id: '583f8bc0-8eee-4b78-9299-1e14fc91e409' | ||||
| 		}, | ||||
|  | ||||
| 		noSuchUser: { | ||||
| 			message: 'No such user.', | ||||
| 			code: 'NO_SUCH_USER', | ||||
| 			id: 'da52de61-002c-475b-90e1-ba64f9cf13a8' | ||||
| 		}, | ||||
|  | ||||
| 		alreadyAdded: { | ||||
| 			message: 'That user has already been added to that group.', | ||||
| 			code: 'ALREADY_ADDED', | ||||
| 			id: '7e35c6a0-39b2-4488-aea6-6ee20bd5da2c' | ||||
| 		} | ||||
| 	} | ||||
| }; | ||||
|  | ||||
| export default define(meta, async (ps, me) => { | ||||
| 	// Fetch the group | ||||
| 	const userGroup = await UserGroups.findOne({ | ||||
| 		id: ps.groupId, | ||||
| 		userId: me.id, | ||||
| 	}); | ||||
|  | ||||
| 	if (userGroup == null) { | ||||
| 		throw new ApiError(meta.errors.noSuchGroup); | ||||
| 	} | ||||
|  | ||||
| 	// Fetch the user | ||||
| 	const user = await getUser(ps.userId).catch(e => { | ||||
| 		if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError(meta.errors.noSuchUser); | ||||
| 		throw e; | ||||
| 	}); | ||||
|  | ||||
| 	const exist = await UserGroupJoinings.findOne({ | ||||
| 		userGroupId: userGroup.id, | ||||
| 		userId: user.id | ||||
| 	}); | ||||
|  | ||||
| 	if (exist) { | ||||
| 		throw new ApiError(meta.errors.alreadyAdded); | ||||
| 	} | ||||
|  | ||||
| 	// Push the user | ||||
| 	await UserGroupJoinings.save({ | ||||
| 		id: genId(), | ||||
| 		createdAt: new Date(), | ||||
| 		userId: user.id, | ||||
| 		userGroupId: userGroup.id | ||||
| 	} as UserGroupJoining); | ||||
| }); | ||||
							
								
								
									
										53
									
								
								src/server/api/endpoints/users/groups/show.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								src/server/api/endpoints/users/groups/show.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,53 @@ | ||||
| import $ from 'cafy'; | ||||
| import { ID } from '../../../../../misc/cafy-id'; | ||||
| import define from '../../../define'; | ||||
| import { ApiError } from '../../../error'; | ||||
| import { UserGroups } from '../../../../../models'; | ||||
| import { types, bool } from '../../../../../misc/schema'; | ||||
|  | ||||
| export const meta = { | ||||
| 	desc: { | ||||
| 		'ja-JP': '指定したユーザーグループの情報を取得します。', | ||||
| 		'en-US': 'Show a user group.' | ||||
| 	}, | ||||
|  | ||||
| 	tags: ['groups', 'account'], | ||||
|  | ||||
| 	requireCredential: true, | ||||
|  | ||||
| 	kind: 'read:user-groups', | ||||
|  | ||||
| 	params: { | ||||
| 		groupId: { | ||||
| 			validator: $.type(ID), | ||||
| 		}, | ||||
| 	}, | ||||
|  | ||||
| 	res: { | ||||
| 		type: types.object, | ||||
| 		optional: bool.false, nullable: bool.false, | ||||
| 		ref: 'UserGroup', | ||||
| 	}, | ||||
|  | ||||
| 	errors: { | ||||
| 		noSuchGroup: { | ||||
| 			message: 'No such group.', | ||||
| 			code: 'NO_SUCH_GROUP', | ||||
| 			id: 'ea04751e-9b7e-487b-a509-330fb6bd6b9b' | ||||
| 		}, | ||||
| 	} | ||||
| }; | ||||
|  | ||||
| export default define(meta, async (ps, me) => { | ||||
| 	// Fetch the group | ||||
| 	const userGroup = await UserGroups.findOne({ | ||||
| 		id: ps.groupId, | ||||
| 		userId: me.id, | ||||
| 	}); | ||||
|  | ||||
| 	if (userGroup == null) { | ||||
| 		throw new ApiError(meta.errors.noSuchGroup); | ||||
| 	} | ||||
|  | ||||
| 	return await UserGroups.pack(userGroup); | ||||
| }); | ||||
| @@ -80,5 +80,5 @@ export default define(meta, async (ps, me) => { | ||||
| 	} | ||||
|  | ||||
| 	// Push the user | ||||
| 	pushUserToUserList(user, userList); | ||||
| 	await pushUserToUserList(user, userList); | ||||
| }); | ||||
|   | ||||
| @@ -23,4 +23,6 @@ export const kinds = [ | ||||
| 	'write:pages', | ||||
| 	'write:page-likes', | ||||
| 	'read:page-likes', | ||||
| 	'read:user-groups', | ||||
| 	'write:user-groups', | ||||
| ]; | ||||
|   | ||||
| @@ -13,6 +13,7 @@ import { packedBlockingSchema } from '../../../models/repositories/blocking'; | ||||
| import { packedNoteReactionSchema } from '../../../models/repositories/note-reaction'; | ||||
| import { packedHashtagSchema } from '../../../models/repositories/hashtag'; | ||||
| import { packedPageSchema } from '../../../models/repositories/page'; | ||||
| import { packedUserGroupSchema } from '../../../models/repositories/user-group'; | ||||
|  | ||||
| export function convertSchemaToOpenApiSchema(schema: Schema) { | ||||
| 	const res: any = schema; | ||||
| @@ -66,6 +67,7 @@ export const schemas = { | ||||
|  | ||||
| 	User: convertSchemaToOpenApiSchema(packedUserSchema), | ||||
| 	UserList: convertSchemaToOpenApiSchema(packedUserListSchema), | ||||
| 	UserGroup: convertSchemaToOpenApiSchema(packedUserGroupSchema), | ||||
| 	App: convertSchemaToOpenApiSchema(packedAppSchema), | ||||
| 	MessagingMessage: convertSchemaToOpenApiSchema(packedMessagingMessageSchema), | ||||
| 	Note: convertSchemaToOpenApiSchema(packedNoteSchema), | ||||
|   | ||||
| @@ -1,20 +1,39 @@ | ||||
| import autobind from 'autobind-decorator'; | ||||
| import read from '../../common/read-messaging-message'; | ||||
| import { readUserMessagingMessage, readGroupMessagingMessage } from '../../common/read-messaging-message'; | ||||
| import Channel from '../channel'; | ||||
| import { UserGroupJoinings } from '../../../../models'; | ||||
|  | ||||
| export default class extends Channel { | ||||
| 	public readonly chName = 'messaging'; | ||||
| 	public static shouldShare = false; | ||||
| 	public static requireCredential = true; | ||||
|  | ||||
| 	private otherpartyId: string; | ||||
| 	private otherpartyId: string | null; | ||||
| 	private groupId: string | null; | ||||
|  | ||||
| 	@autobind | ||||
| 	public async init(params: any) { | ||||
| 		this.otherpartyId = params.otherparty as string; | ||||
| 		this.groupId = params.group as string; | ||||
|  | ||||
| 		// Check joining | ||||
| 		if (this.groupId) { | ||||
| 			const joining = await UserGroupJoinings.findOne({ | ||||
| 				userId: this.user!.id, | ||||
| 				userGroupId: this.groupId | ||||
| 			}); | ||||
|  | ||||
| 			if (joining == null) { | ||||
| 				return; | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		const subCh = this.otherpartyId | ||||
| 			? `messagingStream:${this.user!.id}-${this.otherpartyId}` | ||||
| 			: `messagingStream:${this.groupId}`; | ||||
|  | ||||
| 		// Subscribe messaging stream | ||||
| 		this.subscriber.on(`messagingStream:${this.user!.id}-${this.otherpartyId}`, data => { | ||||
| 		this.subscriber.on(subCh, data => { | ||||
| 			this.send(data); | ||||
| 		}); | ||||
| 	} | ||||
| @@ -23,7 +42,11 @@ export default class extends Channel { | ||||
| 	public onMessage(type: string, body: any) { | ||||
| 		switch (type) { | ||||
| 			case 'read': | ||||
| 				read(this.user!.id, this.otherpartyId, [body.id]); | ||||
| 				if (this.otherpartyId) { | ||||
| 					readUserMessagingMessage(this.user!.id, this.otherpartyId, [body.id]); | ||||
| 				} else if (this.groupId) { | ||||
| 					readGroupMessagingMessage(this.user!.id, this.groupId, [body.id]); | ||||
| 				} | ||||
| 				break; | ||||
| 		} | ||||
| 	} | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 syuilo
					syuilo