X-Git-Url: https://git.immae.eu/?a=blobdiff_plain;ds=sidebyside;f=server%2Fmodels%2Fvideo%2Fvideo-comment.ts;h=f84c1880c6a564fc11c61959514450e25e121e3c;hb=eacb25c4366bcc8fba20f98f93f004fabc6d5578;hp=ab909b0b81c3ea9ecda79ff180a7a07d3da58892;hpb=f05a1c30c15d2ae35c11e241ca039a72eeb7d6ad;p=github%2FChocobozzz%2FPeerTube.git diff --git a/server/models/video/video-comment.ts b/server/models/video/video-comment.ts index ab909b0b8..f84c1880c 100644 --- a/server/models/video/video-comment.ts +++ b/server/models/video/video-comment.ts @@ -104,6 +104,13 @@ enum ScopeNames { }, { fields: [ 'videoId', 'originCommentId' ] + }, + { + fields: [ 'url' ], + unique: true + }, + { + fields: [ 'accountId' ] } ] }) @@ -149,7 +156,7 @@ export class VideoCommentModel extends Model { as: 'InReplyToVideoComment', onDelete: 'CASCADE' }) - InReplyToVideoComment: VideoCommentModel + InReplyToVideoComment: VideoCommentModel | null @ForeignKey(() => VideoModel) @Column @@ -184,6 +191,27 @@ export class VideoCommentModel extends Model { }) as AccountModel } + if (!instance.Video) { + instance.Video = await instance.$get('Video', { + include: [ + { + model: VideoChannelModel, + include: [ + { + model: AccountModel, + include: [ + { + model: ActorModel + } + ] + } + ] + } + ], + transaction: options.transaction + }) as VideoModel + } + if (instance.isOwned()) { await sendDeleteVideoComment(instance, options.transaction) } @@ -243,7 +271,7 @@ export class VideoCommentModel extends Model { const query = { offset: start, limit: count, - order: [ getSort(sort) ], + order: getSort(sort), where: { videoId, inReplyToCommentId: null @@ -282,15 +310,15 @@ export class VideoCommentModel extends Model { const query = { order: [ [ 'createdAt', order ] ], where: { - [ Sequelize.Op.or ]: [ - { id: comment.getThreadId() }, - { originCommentId: comment.getThreadId() } - ], id: { + [ Sequelize.Op.in ]: Sequelize.literal('(' + + 'WITH RECURSIVE children (id, "inReplyToCommentId") AS ( ' + + 'SELECT id, "inReplyToCommentId" FROM "videoComment" WHERE id = ' + comment.id + ' UNION ' + + 'SELECT p.id, p."inReplyToCommentId" from "videoComment" p ' + + 'INNER JOIN children c ON c."inReplyToCommentId" = p.id) ' + + 'SELECT id FROM children' + + ')'), [ Sequelize.Op.ne ]: comment.id - }, - createdAt: { - [ Sequelize.Op.lt ]: comment.createdAt } }, transaction: t @@ -301,6 +329,68 @@ export class VideoCommentModel extends Model { .findAll(query) } + static listAndCountByVideoId (videoId: number, start: number, count: number, t?: Sequelize.Transaction, order: 'ASC' | 'DESC' = 'ASC') { + const query = { + order: [ [ 'createdAt', order ] ], + offset: start, + limit: count, + where: { + videoId + }, + transaction: t + } + + return VideoCommentModel.findAndCountAll(query) + } + + static listForFeed (start: number, count: number, videoId?: number) { + const query = { + order: [ [ 'createdAt', 'DESC' ] ], + offset: start, + limit: count, + where: {}, + include: [ + { + attributes: [ 'name', 'uuid' ], + model: VideoModel.unscoped(), + required: true + } + ] + } + + if (videoId) query.where['videoId'] = videoId + + return VideoCommentModel + .scope([ ScopeNames.WITH_ACCOUNT ]) + .findAll(query) + } + + static async getStats () { + const totalLocalVideoComments = await VideoCommentModel.count({ + include: [ + { + model: AccountModel, + required: true, + include: [ + { + model: ActorModel, + required: true, + where: { + serverId: null + } + } + ] + } + ] + }) + const totalVideoComments = await VideoCommentModel.count() + + return { + totalLocalVideoComments, + totalVideoComments + } + } + getThreadId (): number { return this.originCommentId || this.id }