]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - server/models/video/video-abuse.ts
Add video channel and video thumbnail, rework video appearance in row
[github/Chocobozzz/PeerTube.git] / server / models / video / video-abuse.ts
CommitLineData
86521a67
RK
1import {
2 AllowNull, BelongsTo, Column, CreatedAt, DataType, Default, ForeignKey, Is, Model, Table, UpdatedAt, DefaultScope
3} from 'sequelize-typescript'
3fd3ab2d 4import { VideoAbuseObject } from '../../../shared/models/activitypub/objects'
19a3b914 5import { VideoAbuse } from '../../../shared/models/videos'
268eebed
C
6import {
7 isVideoAbuseModerationCommentValid,
8 isVideoAbuseReasonValid,
9 isVideoAbuseStateValid
10} from '../../helpers/custom-validators/video-abuses'
3fd3ab2d 11import { AccountModel } from '../account/account'
f0a47bc9 12import { buildBlockedAccountSQL, getSort, throwIfNotValid } from '../utils'
3fd3ab2d 13import { VideoModel } from './video'
68d19a0a 14import { VideoAbuseState, Video } from '../../../shared'
74dc3bca 15import { CONSTRAINTS_FIELDS, VIDEO_ABUSE_STATES } from '../../initializers/constants'
f0a47bc9 16import { MUserAccountId, MVideoAbuse, MVideoAbuseFormattable, MVideoAbuseVideo } from '../../typings/models'
453e83ea 17import * as Bluebird from 'bluebird'
f0a47bc9 18import { literal, Op } from 'sequelize'
86521a67
RK
19import { ThumbnailModel } from './thumbnail'
20import { VideoChannelModel } from './video-channel'
21import { ActorModel } from '../activitypub/actor'
22import { VideoBlacklistModel } from './video-blacklist'
3fd3ab2d 23
86521a67
RK
24@DefaultScope(() => ({
25 include: [
26 {
27 model: AccountModel,
28 required: true
29 },
30 {
31 model: VideoModel,
32 required: false,
33 include: [
34 {
35 model: ThumbnailModel
36 },
37 {
38 model: VideoChannelModel.unscoped(),
39 include: [
40 {
41 model: ActorModel
42 }
43 ]
44 },
45 {
46 attributes: [ 'id', 'reason', 'unfederated' ],
47 model: VideoBlacklistModel
48 }
49 ]
50 }
51 ]
52}))
3fd3ab2d
C
53@Table({
54 tableName: 'videoAbuse',
55 indexes: [
55fa55a9 56 {
3fd3ab2d 57 fields: [ 'videoId' ]
55fa55a9
C
58 },
59 {
3fd3ab2d 60 fields: [ 'reporterAccountId' ]
55fa55a9 61 }
e02643f3 62 ]
3fd3ab2d
C
63})
64export class VideoAbuseModel extends Model<VideoAbuseModel> {
e02643f3 65
3fd3ab2d 66 @AllowNull(false)
1506307f 67 @Default(null)
3fd3ab2d 68 @Is('VideoAbuseReason', value => throwIfNotValid(value, isVideoAbuseReasonValid, 'reason'))
1506307f 69 @Column(DataType.STRING(CONSTRAINTS_FIELDS.VIDEO_ABUSES.REASON.max))
3fd3ab2d 70 reason: string
21e0727a 71
268eebed
C
72 @AllowNull(false)
73 @Default(null)
74 @Is('VideoAbuseState', value => throwIfNotValid(value, isVideoAbuseStateValid, 'state'))
75 @Column
76 state: VideoAbuseState
77
78 @AllowNull(true)
79 @Default(null)
1735c825 80 @Is('VideoAbuseModerationComment', value => throwIfNotValid(value, isVideoAbuseModerationCommentValid, 'moderationComment', true))
268eebed
C
81 @Column(DataType.STRING(CONSTRAINTS_FIELDS.VIDEO_ABUSES.MODERATION_COMMENT.max))
82 moderationComment: string
83
68d19a0a
RK
84 @AllowNull(true)
85 @Default(null)
86 @Column(DataType.JSONB)
87 deletedVideo: Video
88
3fd3ab2d
C
89 @CreatedAt
90 createdAt: Date
21e0727a 91
3fd3ab2d
C
92 @UpdatedAt
93 updatedAt: Date
e02643f3 94
3fd3ab2d
C
95 @ForeignKey(() => AccountModel)
96 @Column
97 reporterAccountId: number
55fa55a9 98
3fd3ab2d 99 @BelongsTo(() => AccountModel, {
55fa55a9 100 foreignKey: {
68d19a0a 101 allowNull: true
55fa55a9 102 },
68d19a0a 103 onDelete: 'set null'
55fa55a9 104 })
3fd3ab2d
C
105 Account: AccountModel
106
107 @ForeignKey(() => VideoModel)
108 @Column
109 videoId: number
55fa55a9 110
3fd3ab2d 111 @BelongsTo(() => VideoModel, {
55fa55a9 112 foreignKey: {
68d19a0a 113 allowNull: true
55fa55a9 114 },
68d19a0a 115 onDelete: 'set null'
55fa55a9 116 })
3fd3ab2d
C
117 Video: VideoModel
118
68d19a0a
RK
119 static loadByIdAndVideoId (id: number, videoId?: number, uuid?: string): Bluebird<MVideoAbuse> {
120 const videoAttributes = {}
121 if (videoId) videoAttributes['videoId'] = videoId
122 if (uuid) videoAttributes['deletedVideo'] = { uuid }
123
268eebed
C
124 const query = {
125 where: {
126 id,
68d19a0a 127 ...videoAttributes
268eebed
C
128 }
129 }
130 return VideoAbuseModel.findOne(query)
131 }
132
f0a47bc9 133 static listForApi (parameters: {
a1587156
C
134 start: number
135 count: number
136 sort: string
f0a47bc9
C
137 serverAccountId: number
138 user?: MUserAccountId
139 }) {
140 const { start, count, sort, user, serverAccountId } = parameters
141 const userAccountId = user ? user.Account.id : undefined
142
3fd3ab2d
C
143 const query = {
144 offset: start,
145 limit: count,
3bb6c526 146 order: getSort(sort),
f0a47bc9
C
147 where: {
148 reporterAccountId: {
149 [Op.notIn]: literal('(' + buildBlockedAccountSQL(serverAccountId, userAccountId) + ')')
150 }
151 },
86521a67
RK
152 col: 'VideoAbuseModel.id',
153 distinct: true
3fd3ab2d 154 }
55fa55a9 155
3fd3ab2d
C
156 return VideoAbuseModel.findAndCountAll(query)
157 .then(({ rows, count }) => {
158 return { total: count, data: rows }
159 })
55fa55a9
C
160 }
161
1ca9f7c3 162 toFormattedJSON (this: MVideoAbuseFormattable): VideoAbuse {
68d19a0a
RK
163 const video = this.Video
164 ? this.Video
165 : this.deletedVideo
166
3fd3ab2d
C
167 return {
168 id: this.id,
169 reason: this.reason,
19a3b914 170 reporterAccount: this.Account.toFormattedJSON(),
268eebed
C
171 state: {
172 id: this.state,
173 label: VideoAbuseModel.getStateLabel(this.state)
174 },
175 moderationComment: this.moderationComment,
19a3b914 176 video: {
68d19a0a
RK
177 id: video.id,
178 uuid: video.uuid,
179 name: video.name,
180 nsfw: video.nsfw,
86521a67
RK
181 deleted: !this.Video,
182 blacklisted: this.Video && this.Video.isBlacklisted(),
183 thumbnailPath: this.Video?.getMiniatureStaticPath(),
184 channel: this.Video?.VideoChannel.toFormattedSummaryJSON() || this.deletedVideo?.channel
19a3b914 185 },
3fd3ab2d
C
186 createdAt: this.createdAt
187 }
188 }
189
453e83ea 190 toActivityPubObject (this: MVideoAbuseVideo): VideoAbuseObject {
3fd3ab2d
C
191 return {
192 type: 'Flag' as 'Flag',
193 content: this.reason,
194 object: this.Video.url
195 }
196 }
268eebed
C
197
198 private static getStateLabel (id: number) {
199 return VIDEO_ABUSE_STATES[id] || 'Unknown'
200 }
55fa55a9 201}