aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/models/account/user-notification.ts
diff options
context:
space:
mode:
Diffstat (limited to 'server/models/account/user-notification.ts')
-rw-r--r--server/models/account/user-notification.ts256
1 files changed, 256 insertions, 0 deletions
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 @@
1import { AllowNull, BelongsTo, Column, CreatedAt, Default, ForeignKey, Is, Model, Scopes, Table, UpdatedAt } from 'sequelize-typescript'
2import { UserNotification, UserNotificationType } from '../../../shared'
3import { getSort, throwIfNotValid } from '../utils'
4import { isBooleanValid } from '../../helpers/custom-validators/misc'
5import { isUserNotificationTypeValid } from '../../helpers/custom-validators/user-notifications'
6import { UserModel } from './user'
7import { VideoModel } from '../video/video'
8import { VideoCommentModel } from '../video/video-comment'
9import { Op } from 'sequelize'
10import { VideoChannelModel } from '../video/video-channel'
11import { AccountModel } from './account'
12import { VideoAbuseModel } from '../video/video-abuse'
13import { VideoBlacklistModel } from '../video/video-blacklist'
14
15enum ScopeNames {
16 WITH_ALL = 'WITH_ALL'
17}
18
19@Scopes({
20 [ScopeNames.WITH_ALL]: {
21 include: [
22 {
23 attributes: [ 'id', 'uuid', 'name' ],
24 model: () => VideoModel.unscoped(),
25 required: false,
26 include: [
27 {
28 required: true,
29 attributes: [ 'id', 'name' ],
30 model: () => VideoChannelModel.unscoped()
31 }
32 ]
33 },
34 {
35 attributes: [ 'id' ],
36 model: () => VideoCommentModel.unscoped(),
37 required: false,
38 include: [
39 {
40 required: true,
41 attributes: [ 'id', 'name' ],
42 model: () => AccountModel.unscoped()
43 },
44 {
45 required: true,
46 attributes: [ 'id', 'uuid', 'name' ],
47 model: () => VideoModel.unscoped()
48 }
49 ]
50 },
51 {
52 attributes: [ 'id' ],
53 model: () => VideoAbuseModel.unscoped(),
54 required: false,
55 include: [
56 {
57 required: true,
58 attributes: [ 'id', 'uuid', 'name' ],
59 model: () => VideoModel.unscoped()
60 }
61 ]
62 },
63 {
64 attributes: [ 'id' ],
65 model: () => VideoBlacklistModel.unscoped(),
66 required: false,
67 include: [
68 {
69 required: true,
70 attributes: [ 'id', 'uuid', 'name' ],
71 model: () => VideoModel.unscoped()
72 }
73 ]
74 }
75 ]
76 }
77})
78@Table({
79 tableName: 'userNotification',
80 indexes: [
81 {
82 fields: [ 'videoId' ]
83 },
84 {
85 fields: [ 'commentId' ]
86 }
87 ]
88})
89export class UserNotificationModel extends Model<UserNotificationModel> {
90
91 @AllowNull(false)
92 @Default(null)
93 @Is('UserNotificationType', value => throwIfNotValid(value, isUserNotificationTypeValid, 'type'))
94 @Column
95 type: UserNotificationType
96
97 @AllowNull(false)
98 @Default(false)
99 @Is('UserNotificationRead', value => throwIfNotValid(value, isBooleanValid, 'read'))
100 @Column
101 read: boolean
102
103 @CreatedAt
104 createdAt: Date
105
106 @UpdatedAt
107 updatedAt: Date
108
109 @ForeignKey(() => UserModel)
110 @Column
111 userId: number
112
113 @BelongsTo(() => UserModel, {
114 foreignKey: {
115 allowNull: false
116 },
117 onDelete: 'cascade'
118 })
119 User: UserModel
120
121 @ForeignKey(() => VideoModel)
122 @Column
123 videoId: number
124
125 @BelongsTo(() => VideoModel, {
126 foreignKey: {
127 allowNull: true
128 },
129 onDelete: 'cascade'
130 })
131 Video: VideoModel
132
133 @ForeignKey(() => VideoCommentModel)
134 @Column
135 commentId: number
136
137 @BelongsTo(() => VideoCommentModel, {
138 foreignKey: {
139 allowNull: true
140 },
141 onDelete: 'cascade'
142 })
143 Comment: VideoCommentModel
144
145 @ForeignKey(() => VideoAbuseModel)
146 @Column
147 videoAbuseId: number
148
149 @BelongsTo(() => VideoAbuseModel, {
150 foreignKey: {
151 allowNull: true
152 },
153 onDelete: 'cascade'
154 })
155 VideoAbuse: VideoAbuseModel
156
157 @ForeignKey(() => VideoBlacklistModel)
158 @Column
159 videoBlacklistId: number
160
161 @BelongsTo(() => VideoBlacklistModel, {
162 foreignKey: {
163 allowNull: true
164 },
165 onDelete: 'cascade'
166 })
167 VideoBlacklist: VideoBlacklistModel
168
169 static listForApi (userId: number, start: number, count: number, sort: string) {
170 const query = {
171 offset: start,
172 limit: count,
173 order: getSort(sort),
174 where: {
175 userId
176 }
177 }
178
179 return UserNotificationModel.scope(ScopeNames.WITH_ALL)
180 .findAndCountAll(query)
181 .then(({ rows, count }) => {
182 return {
183 data: rows,
184 total: count
185 }
186 })
187 }
188
189 static markAsRead (userId: number, notificationIds: number[]) {
190 const query = {
191 where: {
192 userId,
193 id: {
194 [Op.any]: notificationIds
195 }
196 }
197 }
198
199 return UserNotificationModel.update({ read: true }, query)
200 }
201
202 toFormattedJSON (): UserNotification {
203 const video = this.Video ? {
204 id: this.Video.id,
205 uuid: this.Video.uuid,
206 name: this.Video.name,
207 channel: {
208 id: this.Video.VideoChannel.id,
209 displayName: this.Video.VideoChannel.getDisplayName()
210 }
211 } : undefined
212
213 const comment = this.Comment ? {
214 id: this.Comment.id,
215 account: {
216 id: this.Comment.Account.id,
217 displayName: this.Comment.Account.getDisplayName()
218 },
219 video: {
220 id: this.Comment.Video.id,
221 uuid: this.Comment.Video.uuid,
222 name: this.Comment.Video.name
223 }
224 } : undefined
225
226 const videoAbuse = this.VideoAbuse ? {
227 id: this.VideoAbuse.id,
228 video: {
229 id: this.VideoAbuse.Video.id,
230 uuid: this.VideoAbuse.Video.uuid,
231 name: this.VideoAbuse.Video.name
232 }
233 } : undefined
234
235 const videoBlacklist = this.VideoBlacklist ? {
236 id: this.VideoBlacklist.id,
237 video: {
238 id: this.VideoBlacklist.Video.id,
239 uuid: this.VideoBlacklist.Video.uuid,
240 name: this.VideoBlacklist.Video.name
241 }
242 } : undefined
243
244 return {
245 id: this.id,
246 type: this.type,
247 read: this.read,
248 video,
249 comment,
250 videoAbuse,
251 videoBlacklist,
252 createdAt: this.createdAt.toISOString(),
253 updatedAt: this.updatedAt.toISOString()
254 }
255 }
256}