]>
Commit | Line | Data |
---|---|---|
1 | import * as Bluebird from 'bluebird' | |
2 | import { AllowNull, BelongsTo, Column, CreatedAt, DataType, ForeignKey, Is, Model, Scopes, Table, UpdatedAt } from 'sequelize-typescript' | |
3 | import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc' | |
4 | import { CONSTRAINTS_FIELDS } from '../../initializers/constants' | |
5 | import { AccountModel } from '../account/account' | |
6 | import { ActorModel } from '../activitypub/actor' | |
7 | import { buildLocalActorIdsIn, throwIfNotValid } from '../utils' | |
8 | import { VideoModel } from './video' | |
9 | import { VideoChannelModel } from './video-channel' | |
10 | import { Op, Transaction } from 'sequelize' | |
11 | import { MVideoShareActor, MVideoShareFull } from '../../typings/models/video' | |
12 | import { MActorDefault } from '../../typings/models' | |
13 | ||
14 | enum ScopeNames { | |
15 | FULL = 'FULL', | |
16 | WITH_ACTOR = 'WITH_ACTOR' | |
17 | } | |
18 | ||
19 | @Scopes(() => ({ | |
20 | [ScopeNames.FULL]: { | |
21 | include: [ | |
22 | { | |
23 | model: ActorModel, | |
24 | required: true | |
25 | }, | |
26 | { | |
27 | model: VideoModel, | |
28 | required: true | |
29 | } | |
30 | ] | |
31 | }, | |
32 | [ScopeNames.WITH_ACTOR]: { | |
33 | include: [ | |
34 | { | |
35 | model: ActorModel, | |
36 | required: true | |
37 | } | |
38 | ] | |
39 | } | |
40 | })) | |
41 | @Table({ | |
42 | tableName: 'videoShare', | |
43 | indexes: [ | |
44 | { | |
45 | fields: [ 'actorId' ] | |
46 | }, | |
47 | { | |
48 | fields: [ 'videoId' ] | |
49 | }, | |
50 | { | |
51 | fields: [ 'url' ], | |
52 | unique: true | |
53 | } | |
54 | ] | |
55 | }) | |
56 | export class VideoShareModel extends Model<VideoShareModel> { | |
57 | ||
58 | @AllowNull(false) | |
59 | @Is('VideoShareUrl', value => throwIfNotValid(value, isActivityPubUrlValid, 'url')) | |
60 | @Column(DataType.STRING(CONSTRAINTS_FIELDS.VIDEO_SHARE.URL.max)) | |
61 | url: string | |
62 | ||
63 | @CreatedAt | |
64 | createdAt: Date | |
65 | ||
66 | @UpdatedAt | |
67 | updatedAt: Date | |
68 | ||
69 | @ForeignKey(() => ActorModel) | |
70 | @Column | |
71 | actorId: number | |
72 | ||
73 | @BelongsTo(() => ActorModel, { | |
74 | foreignKey: { | |
75 | allowNull: false | |
76 | }, | |
77 | onDelete: 'cascade' | |
78 | }) | |
79 | Actor: ActorModel | |
80 | ||
81 | @ForeignKey(() => VideoModel) | |
82 | @Column | |
83 | videoId: number | |
84 | ||
85 | @BelongsTo(() => VideoModel, { | |
86 | foreignKey: { | |
87 | allowNull: false | |
88 | }, | |
89 | onDelete: 'cascade' | |
90 | }) | |
91 | Video: VideoModel | |
92 | ||
93 | static load (actorId: number | string, videoId: number | string, t?: Transaction): Bluebird<MVideoShareActor> { | |
94 | return VideoShareModel.scope(ScopeNames.WITH_ACTOR).findOne({ | |
95 | where: { | |
96 | actorId, | |
97 | videoId | |
98 | }, | |
99 | transaction: t | |
100 | }) | |
101 | } | |
102 | ||
103 | static loadByUrl (url: string, t: Transaction): Bluebird<MVideoShareFull> { | |
104 | return VideoShareModel.scope(ScopeNames.FULL).findOne({ | |
105 | where: { | |
106 | url | |
107 | }, | |
108 | transaction: t | |
109 | }) | |
110 | } | |
111 | ||
112 | static loadActorsByShare (videoId: number, t: Transaction): Bluebird<MActorDefault[]> { | |
113 | const query = { | |
114 | where: { | |
115 | videoId | |
116 | }, | |
117 | include: [ | |
118 | { | |
119 | model: ActorModel, | |
120 | required: true | |
121 | } | |
122 | ], | |
123 | transaction: t | |
124 | } | |
125 | ||
126 | return VideoShareModel.scope(ScopeNames.FULL).findAll(query) | |
127 | .then((res: MVideoShareFull[]) => res.map(r => r.Actor)) | |
128 | } | |
129 | ||
130 | static loadActorsWhoSharedVideosOf (actorOwnerId: number, t: Transaction): Bluebird<MActorDefault[]> { | |
131 | const query = { | |
132 | attributes: [], | |
133 | include: [ | |
134 | { | |
135 | model: ActorModel, | |
136 | required: true | |
137 | }, | |
138 | { | |
139 | attributes: [], | |
140 | model: VideoModel, | |
141 | required: true, | |
142 | include: [ | |
143 | { | |
144 | attributes: [], | |
145 | model: VideoChannelModel.unscoped(), | |
146 | required: true, | |
147 | include: [ | |
148 | { | |
149 | attributes: [], | |
150 | model: AccountModel.unscoped(), | |
151 | required: true, | |
152 | where: { | |
153 | actorId: actorOwnerId | |
154 | } | |
155 | } | |
156 | ] | |
157 | } | |
158 | ] | |
159 | } | |
160 | ], | |
161 | transaction: t | |
162 | } | |
163 | ||
164 | return VideoShareModel.scope(ScopeNames.FULL).findAll(query) | |
165 | .then(res => res.map(r => r.Actor)) | |
166 | } | |
167 | ||
168 | static loadActorsByVideoChannel (videoChannelId: number, t: Transaction): Bluebird<MActorDefault[]> { | |
169 | const query = { | |
170 | attributes: [], | |
171 | include: [ | |
172 | { | |
173 | model: ActorModel, | |
174 | required: true | |
175 | }, | |
176 | { | |
177 | attributes: [], | |
178 | model: VideoModel, | |
179 | required: true, | |
180 | where: { | |
181 | channelId: videoChannelId | |
182 | } | |
183 | } | |
184 | ], | |
185 | transaction: t | |
186 | } | |
187 | ||
188 | return VideoShareModel.scope(ScopeNames.FULL) | |
189 | .findAll(query) | |
190 | .then(res => res.map(r => r.Actor)) | |
191 | } | |
192 | ||
193 | static listAndCountByVideoId (videoId: number, start: number, count: number, t?: Transaction) { | |
194 | const query = { | |
195 | offset: start, | |
196 | limit: count, | |
197 | where: { | |
198 | videoId | |
199 | }, | |
200 | transaction: t | |
201 | } | |
202 | ||
203 | return VideoShareModel.findAndCountAll(query) | |
204 | } | |
205 | ||
206 | static cleanOldSharesOf (videoId: number, beforeUpdatedAt: Date) { | |
207 | const query = { | |
208 | where: { | |
209 | updatedAt: { | |
210 | [Op.lt]: beforeUpdatedAt | |
211 | }, | |
212 | videoId, | |
213 | actorId: { | |
214 | [Op.notIn]: buildLocalActorIdsIn() | |
215 | } | |
216 | } | |
217 | } | |
218 | ||
219 | return VideoShareModel.destroy(query) | |
220 | } | |
221 | } |