From cef534ed53e4518fe0acf581bfe880788d42fc36 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Wed, 26 Dec 2018 10:36:24 +0100 Subject: Add user notification base code --- server/models/account/user-notification.ts | 256 +++++++++++++++++++++++++++++ 1 file changed, 256 insertions(+) create mode 100644 server/models/account/user-notification.ts (limited to 'server/models/account/user-notification.ts') diff --git a/server/models/account/user-notification.ts b/server/models/account/user-notification.ts new file mode 100644 index 000000000..e22f0d57f --- /dev/null +++ b/server/models/account/user-notification.ts @@ -0,0 +1,256 @@ +import { AllowNull, BelongsTo, Column, CreatedAt, Default, ForeignKey, Is, Model, Scopes, Table, UpdatedAt } from 'sequelize-typescript' +import { UserNotification, UserNotificationType } from '../../../shared' +import { getSort, throwIfNotValid } from '../utils' +import { isBooleanValid } from '../../helpers/custom-validators/misc' +import { isUserNotificationTypeValid } from '../../helpers/custom-validators/user-notifications' +import { UserModel } from './user' +import { VideoModel } from '../video/video' +import { VideoCommentModel } from '../video/video-comment' +import { Op } from 'sequelize' +import { VideoChannelModel } from '../video/video-channel' +import { AccountModel } from './account' +import { VideoAbuseModel } from '../video/video-abuse' +import { VideoBlacklistModel } from '../video/video-blacklist' + +enum ScopeNames { + WITH_ALL = 'WITH_ALL' +} + +@Scopes({ + [ScopeNames.WITH_ALL]: { + include: [ + { + attributes: [ 'id', 'uuid', 'name' ], + model: () => VideoModel.unscoped(), + required: false, + include: [ + { + required: true, + attributes: [ 'id', 'name' ], + model: () => VideoChannelModel.unscoped() + } + ] + }, + { + attributes: [ 'id' ], + model: () => VideoCommentModel.unscoped(), + required: false, + include: [ + { + required: true, + attributes: [ 'id', 'name' ], + model: () => AccountModel.unscoped() + }, + { + required: true, + attributes: [ 'id', 'uuid', 'name' ], + model: () => VideoModel.unscoped() + } + ] + }, + { + attributes: [ 'id' ], + model: () => VideoAbuseModel.unscoped(), + required: false, + include: [ + { + required: true, + attributes: [ 'id', 'uuid', 'name' ], + model: () => VideoModel.unscoped() + } + ] + }, + { + attributes: [ 'id' ], + model: () => VideoBlacklistModel.unscoped(), + required: false, + include: [ + { + required: true, + attributes: [ 'id', 'uuid', 'name' ], + model: () => VideoModel.unscoped() + } + ] + } + ] + } +}) +@Table({ + tableName: 'userNotification', + indexes: [ + { + fields: [ 'videoId' ] + }, + { + fields: [ 'commentId' ] + } + ] +}) +export class UserNotificationModel extends Model { + + @AllowNull(false) + @Default(null) + @Is('UserNotificationType', value => throwIfNotValid(value, isUserNotificationTypeValid, 'type')) + @Column + type: UserNotificationType + + @AllowNull(false) + @Default(false) + @Is('UserNotificationRead', value => throwIfNotValid(value, isBooleanValid, 'read')) + @Column + read: boolean + + @CreatedAt + createdAt: Date + + @UpdatedAt + updatedAt: Date + + @ForeignKey(() => UserModel) + @Column + userId: number + + @BelongsTo(() => UserModel, { + foreignKey: { + allowNull: false + }, + onDelete: 'cascade' + }) + User: UserModel + + @ForeignKey(() => VideoModel) + @Column + videoId: number + + @BelongsTo(() => VideoModel, { + foreignKey: { + allowNull: true + }, + onDelete: 'cascade' + }) + Video: VideoModel + + @ForeignKey(() => VideoCommentModel) + @Column + commentId: number + + @BelongsTo(() => VideoCommentModel, { + foreignKey: { + allowNull: true + }, + onDelete: 'cascade' + }) + Comment: VideoCommentModel + + @ForeignKey(() => VideoAbuseModel) + @Column + videoAbuseId: number + + @BelongsTo(() => VideoAbuseModel, { + foreignKey: { + allowNull: true + }, + onDelete: 'cascade' + }) + VideoAbuse: VideoAbuseModel + + @ForeignKey(() => VideoBlacklistModel) + @Column + videoBlacklistId: number + + @BelongsTo(() => VideoBlacklistModel, { + foreignKey: { + allowNull: true + }, + onDelete: 'cascade' + }) + VideoBlacklist: VideoBlacklistModel + + static listForApi (userId: number, start: number, count: number, sort: string) { + const query = { + offset: start, + limit: count, + order: getSort(sort), + where: { + userId + } + } + + return UserNotificationModel.scope(ScopeNames.WITH_ALL) + .findAndCountAll(query) + .then(({ rows, count }) => { + return { + data: rows, + total: count + } + }) + } + + static markAsRead (userId: number, notificationIds: number[]) { + const query = { + where: { + userId, + id: { + [Op.any]: notificationIds + } + } + } + + return UserNotificationModel.update({ read: true }, query) + } + + toFormattedJSON (): UserNotification { + const video = this.Video ? { + id: this.Video.id, + uuid: this.Video.uuid, + name: this.Video.name, + channel: { + id: this.Video.VideoChannel.id, + displayName: this.Video.VideoChannel.getDisplayName() + } + } : undefined + + const comment = this.Comment ? { + id: this.Comment.id, + account: { + id: this.Comment.Account.id, + displayName: this.Comment.Account.getDisplayName() + }, + video: { + id: this.Comment.Video.id, + uuid: this.Comment.Video.uuid, + name: this.Comment.Video.name + } + } : undefined + + const videoAbuse = this.VideoAbuse ? { + id: this.VideoAbuse.id, + video: { + id: this.VideoAbuse.Video.id, + uuid: this.VideoAbuse.Video.uuid, + name: this.VideoAbuse.Video.name + } + } : undefined + + const videoBlacklist = this.VideoBlacklist ? { + id: this.VideoBlacklist.id, + video: { + id: this.VideoBlacklist.Video.id, + uuid: this.VideoBlacklist.Video.uuid, + name: this.VideoBlacklist.Video.name + } + } : undefined + + return { + id: this.id, + type: this.type, + read: this.read, + video, + comment, + videoAbuse, + videoBlacklist, + createdAt: this.createdAt.toISOString(), + updatedAt: this.updatedAt.toISOString() + } + } +} -- cgit v1.2.3