import { AllowNull, BelongsTo, Column, CreatedAt, DataType, ForeignKey, Is, Model, Scopes, Table, UpdatedAt } from 'sequelize-typescript'
-import { ActivityTagObject } from '../../../shared/models/activitypub/objects/common-objects'
+import { ActivityTagObject, ActivityTombstoneObject } from '../../../shared/models/activitypub/objects/common-objects'
import { VideoCommentObject } from '../../../shared/models/activitypub/objects/video-comment-object'
import { VideoComment } from '../../../shared/models/videos/video-comment.model'
import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc'
import { CONSTRAINTS_FIELDS, WEBSERVER } from '../../initializers/constants'
import { AccountModel } from '../account/account'
import { ActorModel } from '../activitypub/actor'
-import { buildBlockedAccountSQL, buildLocalAccountIdsIn, getSort, throwIfNotValid } from '../utils'
+import { buildBlockedAccountSQL, buildLocalAccountIdsIn, getCommentSort, throwIfNotValid } from '../utils'
import { VideoModel } from './video'
import { VideoChannelModel } from './video-channel'
import { getServerActor } from '../../helpers/utils'
')'
),
'totalReplies'
+ ],
+ [
+ Sequelize.literal(
+ '(' +
+ 'SELECT COUNT("replies"."id") ' +
+ 'FROM "videoComment" AS "replies" ' +
+ 'INNER JOIN "video" ON "video"."id" = "replies"."videoId" ' +
+ 'INNER JOIN "videoChannel" ON "videoChannel"."id" = "video"."channelId" ' +
+ 'WHERE "replies"."originCommentId" = "VideoCommentModel"."id" ' +
+ 'AND "replies"."accountId" = "videoChannel"."accountId"' +
+ ')'
+ ),
+ 'totalRepliesFromVideoAuthor'
]
]
}
@UpdatedAt
updatedAt: Date
+ @AllowNull(true)
+ @Column(DataType.DATE)
+ deletedAt: Date
+
@AllowNull(false)
@Is('VideoCommentUrl', value => throwIfNotValid(value, isActivityPubUrlValid, 'url'))
@Column(DataType.STRING(CONSTRAINTS_FIELDS.VIDEOS.URL.max))
@BelongsTo(() => AccountModel, {
foreignKey: {
- allowNull: false
+ allowNull: true
},
onDelete: 'CASCADE'
})
const query = {
offset: start,
limit: count,
- order: getSort(sort),
+ order: getCommentSort(sort),
where: {
videoId,
inReplyToCommentId: null,
}
isOwned () {
+ if (!this.Account) {
+ return false
+ }
+
return this.Account.isOwned()
}
+ isDeleted () {
+ return null !== this.deletedAt
+ }
+
extractMentions () {
let result: string[] = []
videoId: this.videoId,
createdAt: this.createdAt,
updatedAt: this.updatedAt,
+ deletedAt: this.deletedAt,
+ isDeleted: this.isDeleted(),
+ totalRepliesFromVideoAuthor: this.get('totalRepliesFromVideoAuthor') || 0,
totalReplies: this.get('totalReplies') || 0,
- account: this.Account.toFormattedJSON()
+ account: this.Account ? this.Account.toFormattedJSON() : null
} as VideoComment
}
- toActivityPubObject (this: MCommentAP, threadParentComments: MCommentOwner[]): VideoCommentObject {
+ toActivityPubObject (this: MCommentAP, threadParentComments: MCommentOwner[]): VideoCommentObject | ActivityTombstoneObject {
let inReplyTo: string
// New thread, so in AS we reply to the video
if (this.inReplyToCommentId === null) {
inReplyTo = this.InReplyToVideoComment.url
}
+ if (this.isDeleted()) {
+ return {
+ id: this.url,
+ type: 'Tombstone',
+ formerType: 'Note',
+ inReplyTo,
+ published: this.createdAt.toISOString(),
+ updated: this.updatedAt.toISOString(),
+ deleted: this.deletedAt.toISOString()
+ }
+ }
+
const tag: ActivityTagObject[] = []
for (const parentComment of threadParentComments) {
+ if (!parentComment.Account) continue
+
const actor = parentComment.Account.Actor
tag.push({