]>
Commit | Line | Data |
---|---|---|
6d852470 C |
1 | import * as Sequelize from 'sequelize' |
2 | import { | |
bf1f6508 | 3 | AfterDestroy, AllowNull, BelongsTo, Column, CreatedAt, DataType, ForeignKey, IFindOptions, Is, Model, Scopes, Table, |
6d852470 C |
4 | UpdatedAt |
5 | } from 'sequelize-typescript' | |
bf1f6508 | 6 | import { VideoComment } from '../../../shared/models/videos/video-comment.model' |
6d852470 C |
7 | import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub' |
8 | import { CONSTRAINTS_FIELDS } from '../../initializers' | |
d3ea8975 | 9 | import { AccountModel } from '../account/account' |
bf1f6508 | 10 | import { getSort, throwIfNotValid } from '../utils' |
6d852470 C |
11 | import { VideoModel } from './video' |
12 | ||
bf1f6508 | 13 | enum ScopeNames { |
d3ea8975 | 14 | WITH_ACCOUNT = 'WITH_ACCOUNT' |
bf1f6508 C |
15 | } |
16 | ||
17 | @Scopes({ | |
d3ea8975 | 18 | [ScopeNames.WITH_ACCOUNT]: { |
bf1f6508 | 19 | include: [ |
d3ea8975 | 20 | () => AccountModel |
bf1f6508 C |
21 | ] |
22 | } | |
23 | }) | |
6d852470 C |
24 | @Table({ |
25 | tableName: 'videoComment', | |
26 | indexes: [ | |
27 | { | |
28 | fields: [ 'videoId' ] | |
bf1f6508 C |
29 | }, |
30 | { | |
31 | fields: [ 'videoId', 'originCommentId' ] | |
6d852470 C |
32 | } |
33 | ] | |
34 | }) | |
35 | export class VideoCommentModel extends Model<VideoCommentModel> { | |
36 | @CreatedAt | |
37 | createdAt: Date | |
38 | ||
39 | @UpdatedAt | |
40 | updatedAt: Date | |
41 | ||
42 | @AllowNull(false) | |
43 | @Is('VideoCommentUrl', value => throwIfNotValid(value, isActivityPubUrlValid, 'url')) | |
44 | @Column(DataType.STRING(CONSTRAINTS_FIELDS.VIDEOS.URL.max)) | |
45 | url: string | |
46 | ||
47 | @AllowNull(false) | |
48 | @Column(DataType.TEXT) | |
49 | text: string | |
50 | ||
51 | @ForeignKey(() => VideoCommentModel) | |
52 | @Column | |
53 | originCommentId: number | |
54 | ||
55 | @BelongsTo(() => VideoCommentModel, { | |
56 | foreignKey: { | |
57 | allowNull: true | |
58 | }, | |
59 | onDelete: 'CASCADE' | |
60 | }) | |
61 | OriginVideoComment: VideoCommentModel | |
62 | ||
63 | @ForeignKey(() => VideoCommentModel) | |
64 | @Column | |
65 | inReplyToCommentId: number | |
66 | ||
67 | @BelongsTo(() => VideoCommentModel, { | |
68 | foreignKey: { | |
69 | allowNull: true | |
70 | }, | |
71 | onDelete: 'CASCADE' | |
72 | }) | |
73 | InReplyToVideoComment: VideoCommentModel | |
74 | ||
75 | @ForeignKey(() => VideoModel) | |
76 | @Column | |
77 | videoId: number | |
78 | ||
79 | @BelongsTo(() => VideoModel, { | |
80 | foreignKey: { | |
81 | allowNull: false | |
82 | }, | |
83 | onDelete: 'CASCADE' | |
84 | }) | |
85 | Video: VideoModel | |
86 | ||
d3ea8975 | 87 | @ForeignKey(() => AccountModel) |
6d852470 | 88 | @Column |
d3ea8975 | 89 | accountId: number |
6d852470 | 90 | |
d3ea8975 | 91 | @BelongsTo(() => AccountModel, { |
6d852470 C |
92 | foreignKey: { |
93 | allowNull: false | |
94 | }, | |
95 | onDelete: 'CASCADE' | |
96 | }) | |
d3ea8975 | 97 | Account: AccountModel |
6d852470 | 98 | |
bf1f6508 C |
99 | @AfterDestroy |
100 | static sendDeleteIfOwned (instance: VideoCommentModel) { | |
101 | // TODO | |
102 | return undefined | |
103 | } | |
104 | ||
105 | static loadById (id: number, t?: Sequelize.Transaction) { | |
106 | const query: IFindOptions<VideoCommentModel> = { | |
107 | where: { | |
108 | id | |
109 | } | |
110 | } | |
111 | ||
112 | if (t !== undefined) query.transaction = t | |
113 | ||
114 | return VideoCommentModel.findOne(query) | |
115 | } | |
116 | ||
6d852470 C |
117 | static loadByUrl (url: string, t?: Sequelize.Transaction) { |
118 | const query: IFindOptions<VideoCommentModel> = { | |
119 | where: { | |
120 | url | |
121 | } | |
122 | } | |
123 | ||
124 | if (t !== undefined) query.transaction = t | |
125 | ||
126 | return VideoCommentModel.findOne(query) | |
127 | } | |
bf1f6508 C |
128 | |
129 | static listThreadsForApi (videoId: number, start: number, count: number, sort: string) { | |
130 | const query = { | |
131 | offset: start, | |
132 | limit: count, | |
133 | order: [ getSort(sort) ], | |
134 | where: { | |
d3ea8975 C |
135 | videoId, |
136 | inReplyToCommentId: null | |
bf1f6508 C |
137 | } |
138 | } | |
139 | ||
140 | return VideoCommentModel | |
d3ea8975 | 141 | .scope([ ScopeNames.WITH_ACCOUNT ]) |
bf1f6508 C |
142 | .findAndCountAll(query) |
143 | .then(({ rows, count }) => { | |
144 | return { total: count, data: rows } | |
145 | }) | |
146 | } | |
147 | ||
148 | static listThreadCommentsForApi (videoId: number, threadId: number) { | |
149 | const query = { | |
d3ea8975 | 150 | order: [ [ 'id', 'ASC' ] ], |
bf1f6508 C |
151 | where: { |
152 | videoId, | |
153 | [ Sequelize.Op.or ]: [ | |
154 | { id: threadId }, | |
155 | { originCommentId: threadId } | |
156 | ] | |
157 | } | |
158 | } | |
159 | ||
160 | return VideoCommentModel | |
d3ea8975 | 161 | .scope([ ScopeNames.WITH_ACCOUNT ]) |
bf1f6508 C |
162 | .findAndCountAll(query) |
163 | .then(({ rows, count }) => { | |
164 | return { total: count, data: rows } | |
165 | }) | |
166 | } | |
167 | ||
168 | toFormattedJSON () { | |
169 | return { | |
170 | id: this.id, | |
171 | url: this.url, | |
172 | text: this.text, | |
173 | threadId: this.originCommentId || this.id, | |
174 | inReplyToCommentId: this.inReplyToCommentId, | |
175 | videoId: this.videoId, | |
176 | createdAt: this.createdAt, | |
d3ea8975 C |
177 | updatedAt: this.updatedAt, |
178 | account: { | |
179 | name: this.Account.name | |
180 | } | |
bf1f6508 C |
181 | } as VideoComment |
182 | } | |
6d852470 | 183 | } |