ユーザーグループ

Resolve #3218
This commit is contained in:
syuilo 2019-05-18 20:36:33 +09:00
parent 61f54f8f74
commit c7cc3dcdfd
No known key found for this signature in database
GPG key ID: BDC4C49D06AB9D69
65 changed files with 1797 additions and 638 deletions

View file

@ -1,6 +1,6 @@
import { EntityRepository, Repository } from 'typeorm';
import { MessagingMessage } from '../entities/messaging-message';
import { Users, DriveFiles } from '..';
import { Users, DriveFiles, UserGroups } from '..';
import { ensure } from '../../prelude/ensure';
import { types, bool, SchemaType } from '../../misc/schema';
@ -16,11 +16,13 @@ export class MessagingMessageRepository extends Repository<MessagingMessage> {
src: MessagingMessage['id'] | MessagingMessage,
me?: any,
options?: {
populateRecipient: boolean
populateRecipient?: boolean,
populateGroup?: boolean,
}
): Promise<PackedMessagingMessage> {
const opts = options || {
populateRecipient: true
populateRecipient: true,
populateGroup: true,
};
const message = typeof src === 'object' ? src : await this.findOne(src).then(ensure);
@ -32,10 +34,13 @@ export class MessagingMessageRepository extends Repository<MessagingMessage> {
userId: message.userId,
user: await Users.pack(message.user || message.userId, me),
recipientId: message.recipientId,
recipient: opts.populateRecipient ? await Users.pack(message.recipient || message.recipientId, me) : undefined,
recipient: message.recipientId && opts.populateRecipient ? await Users.pack(message.recipient || message.recipientId, me) : undefined,
groupId: message.recipientId,
group: message.groupId && opts.populateGroup ? await UserGroups.pack(message.group || message.groupId) : undefined,
fileId: message.fileId,
file: message.fileId ? await DriveFiles.pack(message.fileId) : null,
isRead: message.isRead
isRead: message.isRead,
reads: message.reads,
};
}
}
@ -83,17 +88,36 @@ export const packedMessagingMessageSchema = {
},
recipientId: {
type: types.string,
optional: bool.false, nullable: bool.false,
optional: bool.false, nullable: bool.true,
format: 'id',
},
recipient: {
type: types.object,
optional: bool.true, nullable: bool.false,
optional: bool.true, nullable: bool.true,
ref: 'User'
},
groupId: {
type: types.string,
optional: bool.false, nullable: bool.true,
format: 'id',
},
group: {
type: types.object,
optional: bool.true, nullable: bool.true,
ref: 'UserGroup'
},
isRead: {
type: types.boolean,
optional: bool.true, nullable: bool.false,
},
reads: {
type: types.array,
optional: bool.true, nullable: bool.false,
items: {
type: types.string,
optional: bool.false, nullable: bool.false,
format: 'id'
}
},
},
};

View file

@ -0,0 +1,61 @@
import { EntityRepository, Repository } from 'typeorm';
import { UserGroup } from '../entities/user-group';
import { ensure } from '../../prelude/ensure';
import { UserGroupJoinings } from '..';
import { bool, types, SchemaType } from '../../misc/schema';
export type PackedUserGroup = SchemaType<typeof packedUserGroupSchema>;
@EntityRepository(UserGroup)
export class UserGroupRepository extends Repository<UserGroup> {
public async pack(
src: UserGroup['id'] | UserGroup,
): Promise<PackedUserGroup> {
const userGroup = typeof src === 'object' ? src : await this.findOne(src).then(ensure);
const users = await UserGroupJoinings.find({
userGroupId: userGroup.id
});
return {
id: userGroup.id,
createdAt: userGroup.createdAt.toISOString(),
name: userGroup.name,
userIds: users.map(x => x.userId)
};
}
}
export const packedUserGroupSchema = {
type: types.object,
optional: bool.false, nullable: bool.false,
properties: {
id: {
type: types.string,
optional: bool.false, nullable: bool.false,
format: 'id',
description: 'The unique identifier for this UserGroup.',
example: 'xxxxxxxxxx',
},
createdAt: {
type: types.string,
optional: bool.false, nullable: bool.false,
format: 'date-time',
description: 'The date that the UserGroup was created.'
},
name: {
type: types.string,
optional: bool.false, nullable: bool.false,
description: 'The name of the UserGroup.'
},
userIds: {
type: types.array,
nullable: bool.false, optional: bool.true,
items: {
type: types.string,
nullable: bool.false, optional: bool.false,
format: 'id',
}
},
},
};

View file

@ -1,6 +1,6 @@
import { EntityRepository, Repository, In } from 'typeorm';
import { User, ILocalUser, IRemoteUser } from '../entities/user';
import { Emojis, Notes, NoteUnreads, FollowRequests, Notifications, MessagingMessages, UserNotePinings, Followings, Blockings, Mutings, UserProfiles } from '..';
import { Emojis, Notes, NoteUnreads, FollowRequests, Notifications, MessagingMessages, UserNotePinings, Followings, Blockings, Mutings, UserProfiles, UserGroupJoinings } from '..';
import { ensure } from '../../prelude/ensure';
import config from '../../config';
import { SchemaType, bool, types } from '../../misc/schema';
@ -54,6 +54,31 @@ export class UserRepository extends Repository<User> {
};
}
public async getHasUnreadMessagingMessage(userId: User['id']): Promise<boolean> {
const joinings = await UserGroupJoinings.find({ userId: userId });
const groupQs = Promise.all(joinings.map(j => MessagingMessages.createQueryBuilder('message')
.where(`message.groupId = :groupId`, { groupId: j.userGroupId })
.andWhere('message.userId != :userId', { userId: userId })
.andWhere('NOT (:userId = ANY(message.reads))', { userId: userId })
.andWhere('message.createdAt > :joinedAt', { joinedAt: j.createdAt }) // 自分が加入する前の会話については、未読扱いしない
.getOne().then(x => x != null)));
const [withUser, withGroups] = await Promise.all([
// TODO: ミュートを考慮
MessagingMessages.count({
where: {
recipientId: userId,
isRead: false
},
take: 1
}).then(count => count > 0),
groupQs
]);
return withUser || withGroups.some(x => x);
}
public async pack(
src: User['id'] | User,
me?: User['id'] | User | null | undefined,
@ -151,13 +176,7 @@ export class UserRepository extends Repository<User> {
autoWatch: profile!.autoWatch,
alwaysMarkNsfw: profile!.alwaysMarkNsfw,
carefulBot: profile!.carefulBot,
hasUnreadMessagingMessage: MessagingMessages.count({
where: {
recipientId: user.id,
isRead: false
},
take: 1
}).then(count => count > 0),
hasUnreadMessagingMessage: this.getHasUnreadMessagingMessage(user.id),
hasUnreadNotification: Notifications.count({
where: {
notifieeId: user.id,