import { FindOptions, Op, Order, ScopeOptions, Sequelize, Transaction } from 'sequelize'
import { AllowNull, BelongsTo, Column, CreatedAt, DataType, ForeignKey, Is, Model, Scopes, Table, UpdatedAt } from 'sequelize-typescript'
import { getServerActor } from '@server/models/application/application'
import { FindOptions, Op, Order, ScopeOptions, Sequelize, Transaction } from 'sequelize'
import { AllowNull, BelongsTo, Column, CreatedAt, DataType, ForeignKey, Is, Model, Scopes, Table, UpdatedAt } from 'sequelize-typescript'
import { getServerActor } from '@server/models/application/application'
import { VideoPrivacy } from '@shared/models'
import { ActivityTagObject, ActivityTombstoneObject } from '../../../shared/models/activitypub/objects/common-objects'
import { VideoCommentObject } from '../../../shared/models/activitypub/objects/video-comment-object'
import { VideoPrivacy } from '@shared/models'
import { ActivityTagObject, ActivityTombstoneObject } from '../../../shared/models/activitypub/objects/common-objects'
import { VideoCommentObject } from '../../../shared/models/activitypub/objects/video-comment-object'
- MCommentOwnerVideoReply
-} from '../../typings/models/video'
+ MCommentOwnerVideoReply,
+ MVideoImmutable
+} from '../../types/models/video'
import { buildBlockedAccountSQL, buildLocalAccountIdsIn, getCommentSort, throwIfNotValid } from '../utils'
import { VideoModel } from './video'
import { VideoChannelModel } from './video-channel'
enum ScopeNames {
WITH_ACCOUNT = 'WITH_ACCOUNT',
import { buildBlockedAccountSQL, buildLocalAccountIdsIn, getCommentSort, throwIfNotValid } from '../utils'
import { VideoModel } from './video'
import { VideoChannelModel } from './video-channel'
enum ScopeNames {
WITH_ACCOUNT = 'WITH_ACCOUNT',
WITH_IN_REPLY_TO = 'WITH_IN_REPLY_TO',
WITH_VIDEO = 'WITH_VIDEO',
ATTRIBUTES_FOR_API = 'ATTRIBUTES_FOR_API'
}
@Scopes(() => ({
WITH_IN_REPLY_TO = 'WITH_IN_REPLY_TO',
WITH_VIDEO = 'WITH_VIDEO',
ATTRIBUTES_FOR_API = 'ATTRIBUTES_FOR_API'
}
@Scopes(() => ({
'SELECT COUNT("replies"."id") - (' +
'SELECT COUNT("replies"."id") ' +
'FROM "videoComment" AS "replies" ' +
'SELECT COUNT("replies"."id") - (' +
'SELECT COUNT("replies"."id") ' +
'FROM "videoComment" AS "replies" ' +
+ [ScopeNames.WITH_ACCOUNT_FOR_API]: {
+ include: [
+ {
+ model: AccountModel.unscoped(),
+ include: [
+ {
+ attributes: {
+ exclude: unusedActorAttributesForAPI
+ },
+ model: ActorModel, // Default scope includes avatar and server
+ required: true
+ }
+ ]
+ }
+ ]
+ },
- const { videoId, start, count, sort, user } = parameters
+ const { videoId, isVideoOwned, start, count, sort, user } = parameters
- const serverActor = await getServerActor()
- const serverAccountId = serverActor.Account.id
- const userAccountId = user ? user.Account.id : undefined
+ const blockerAccountIds = await VideoCommentModel.buildBlockerAccountIds({ videoId, user, isVideoOwned })
- videoId,
- inReplyToCommentId: null,
- accountId: {
- [Op.notIn]: Sequelize.literal(
- '(' + buildBlockedAccountSQL(serverAccountId, userAccountId) + ')'
- )
- }
+ [Op.and]: [
+ {
+ videoId
+ },
+ {
+ inReplyToCommentId: null
+ },
+ {
+ [Op.or]: [
+ {
+ accountId: {
+ [Op.notIn]: Sequelize.literal(
+ '(' + buildBlockedAccountSQL(blockerAccountIds) + ')'
+ )
+ }
+ },
+ {
+ accountId: null
+ }
+ ]
+ }
+ ]
- const { videoId, threadId, user } = parameters
+ const { videoId, threadId, user, isVideoOwned } = parameters
- const serverActor = await getServerActor()
- const serverAccountId = serverActor.Account.id
- const userAccountId = user ? user.Account.id : undefined
+ const blockerAccountIds = await VideoCommentModel.buildBlockerAccountIds({ videoId, user, isVideoOwned })
const query = {
order: [ [ 'createdAt', 'ASC' ], [ 'updatedAt', 'ASC' ] ] as Order,
const query = {
order: [ [ 'createdAt', 'ASC' ], [ 'updatedAt', 'ASC' ] ] as Order,
- static listAndCountByVideoId (videoId: number, start: number, count: number, t?: Transaction, order: 'ASC' | 'DESC' = 'ASC') {
+ static async listAndCountByVideoForAP (video: MVideoImmutable, start: number, count: number, t?: Transaction) {
+ const blockerAccountIds = await VideoCommentModel.buildBlockerAccountIds({
+ videoId: video.id,
+ isVideoOwned: video.isOwned()
+ })
+
- static async listForFeed (start: number, count: number, videoId?: number): Promise<MCommentOwnerVideoFeed[]> {
+ static async listForFeed (parameters: {
+ start: number
+ count: number
+ videoId?: number
+ accountId?: number
+ videoChannelId?: number
+ }): Promise<MCommentOwnerVideoFeed[]> {
+ const { start, count, videoId, accountId, videoChannelId } = parameters
+
+ const accountExclusion = {
+ [Op.notIn]: Sequelize.literal(
+ '(' + buildBlockedAccountSQL([ serverActor.Account.id, '"Video->VideoChannel"."accountId"' ]) + ')'
+ )
+ }
+ const accountWhere = accountId
+ ? {
+ [Op.and]: {
+ ...accountExclusion,
+ [Op.eq]: accountId
+ }
+ }
+ : accountExclusion
+
+ const videoChannelWhere = videoChannelId ? { id: videoChannelId } : undefined
+
+ private static async buildBlockerAccountIds (options: {
+ videoId: number
+ isVideoOwned: boolean
+ user?: MUserAccountId
+ }) {
+ const { videoId, user, isVideoOwned } = options
+
+ const serverActor = await getServerActor()
+ const blockerAccountIds = [ serverActor.Account.id ]
+
+ if (user) blockerAccountIds.push(user.Account.id)
+
+ if (isVideoOwned) {
+ const videoOwnerAccount = await AccountModel.loadAccountIdFromVideo(videoId)
+ blockerAccountIds.push(videoOwnerAccount.id)
+ }
+
+ return blockerAccountIds
+ }