diff options
Diffstat (limited to 'server/models/video/video-comment.ts')
-rw-r--r-- | server/models/video/video-comment.ts | 446 |
1 files changed, 95 insertions, 351 deletions
diff --git a/server/models/video/video-comment.ts b/server/models/video/video-comment.ts index af9614d30..fb9d15e55 100644 --- a/server/models/video/video-comment.ts +++ b/server/models/video/video-comment.ts | |||
@@ -1,4 +1,4 @@ | |||
1 | import { FindOptions, Op, Order, QueryTypes, ScopeOptions, Sequelize, Transaction, WhereOptions } from 'sequelize' | 1 | import { FindOptions, Op, Order, QueryTypes, Sequelize, Transaction } from 'sequelize' |
2 | import { | 2 | import { |
3 | AllowNull, | 3 | AllowNull, |
4 | BelongsTo, | 4 | BelongsTo, |
@@ -13,11 +13,9 @@ import { | |||
13 | Table, | 13 | Table, |
14 | UpdatedAt | 14 | UpdatedAt |
15 | } from 'sequelize-typescript' | 15 | } from 'sequelize-typescript' |
16 | import { exists } from '@server/helpers/custom-validators/misc' | ||
17 | import { getServerActor } from '@server/models/application/application' | 16 | import { getServerActor } from '@server/models/application/application' |
18 | import { MAccount, MAccountId, MUserAccountId } from '@server/types/models' | 17 | import { MAccount, MAccountId, MUserAccountId } from '@server/types/models' |
19 | import { uniqify } from '@shared/core-utils' | 18 | import { pick, uniqify } from '@shared/core-utils' |
20 | import { VideoPrivacy } from '@shared/models' | ||
21 | import { AttributesOnly } from '@shared/typescript-utils' | 19 | import { AttributesOnly } from '@shared/typescript-utils' |
22 | import { ActivityTagObject, ActivityTombstoneObject } from '../../../shared/models/activitypub/objects/common-objects' | 20 | import { ActivityTagObject, ActivityTombstoneObject } from '../../../shared/models/activitypub/objects/common-objects' |
23 | import { VideoCommentObject } from '../../../shared/models/activitypub/objects/video-comment-object' | 21 | import { VideoCommentObject } from '../../../shared/models/activitypub/objects/video-comment-object' |
@@ -41,61 +39,19 @@ import { | |||
41 | } from '../../types/models/video' | 39 | } from '../../types/models/video' |
42 | import { VideoCommentAbuseModel } from '../abuse/video-comment-abuse' | 40 | import { VideoCommentAbuseModel } from '../abuse/video-comment-abuse' |
43 | import { AccountModel } from '../account/account' | 41 | import { AccountModel } from '../account/account' |
44 | import { ActorModel, unusedActorAttributesForAPI } from '../actor/actor' | 42 | import { ActorModel } from '../actor/actor' |
45 | import { | 43 | import { buildLocalAccountIdsIn, throwIfNotValid } from '../utils' |
46 | buildBlockedAccountSQL, | 44 | import { ListVideoCommentsOptions, VideoCommentListQueryBuilder } from './sql/comment/video-comment-list-query-builder' |
47 | buildBlockedAccountSQLOptimized, | ||
48 | buildLocalAccountIdsIn, | ||
49 | getCommentSort, | ||
50 | searchAttribute, | ||
51 | throwIfNotValid | ||
52 | } from '../utils' | ||
53 | import { VideoModel } from './video' | 45 | import { VideoModel } from './video' |
54 | import { VideoChannelModel } from './video-channel' | 46 | import { VideoChannelModel } from './video-channel' |
55 | 47 | ||
56 | export enum ScopeNames { | 48 | export enum ScopeNames { |
57 | WITH_ACCOUNT = 'WITH_ACCOUNT', | 49 | WITH_ACCOUNT = 'WITH_ACCOUNT', |
58 | WITH_ACCOUNT_FOR_API = 'WITH_ACCOUNT_FOR_API', | ||
59 | WITH_IN_REPLY_TO = 'WITH_IN_REPLY_TO', | 50 | WITH_IN_REPLY_TO = 'WITH_IN_REPLY_TO', |
60 | WITH_VIDEO = 'WITH_VIDEO', | 51 | WITH_VIDEO = 'WITH_VIDEO' |
61 | ATTRIBUTES_FOR_API = 'ATTRIBUTES_FOR_API' | ||
62 | } | 52 | } |
63 | 53 | ||
64 | @Scopes(() => ({ | 54 | @Scopes(() => ({ |
65 | [ScopeNames.ATTRIBUTES_FOR_API]: (blockerAccountIds: number[]) => { | ||
66 | return { | ||
67 | attributes: { | ||
68 | include: [ | ||
69 | [ | ||
70 | Sequelize.literal( | ||
71 | '(' + | ||
72 | 'WITH "blocklist" AS (' + buildBlockedAccountSQL(blockerAccountIds) + ')' + | ||
73 | 'SELECT COUNT("replies"."id") ' + | ||
74 | 'FROM "videoComment" AS "replies" ' + | ||
75 | 'WHERE "replies"."originCommentId" = "VideoCommentModel"."id" ' + | ||
76 | 'AND "deletedAt" IS NULL ' + | ||
77 | 'AND "accountId" NOT IN (SELECT "id" FROM "blocklist")' + | ||
78 | ')' | ||
79 | ), | ||
80 | 'totalReplies' | ||
81 | ], | ||
82 | [ | ||
83 | Sequelize.literal( | ||
84 | '(' + | ||
85 | 'SELECT COUNT("replies"."id") ' + | ||
86 | 'FROM "videoComment" AS "replies" ' + | ||
87 | 'INNER JOIN "video" ON "video"."id" = "replies"."videoId" ' + | ||
88 | 'INNER JOIN "videoChannel" ON "videoChannel"."id" = "video"."channelId" ' + | ||
89 | 'WHERE "replies"."originCommentId" = "VideoCommentModel"."id" ' + | ||
90 | 'AND "replies"."accountId" = "videoChannel"."accountId"' + | ||
91 | ')' | ||
92 | ), | ||
93 | 'totalRepliesFromVideoAuthor' | ||
94 | ] | ||
95 | ] | ||
96 | } | ||
97 | } as FindOptions | ||
98 | }, | ||
99 | [ScopeNames.WITH_ACCOUNT]: { | 55 | [ScopeNames.WITH_ACCOUNT]: { |
100 | include: [ | 56 | include: [ |
101 | { | 57 | { |
@@ -103,22 +59,6 @@ export enum ScopeNames { | |||
103 | } | 59 | } |
104 | ] | 60 | ] |
105 | }, | 61 | }, |
106 | [ScopeNames.WITH_ACCOUNT_FOR_API]: { | ||
107 | include: [ | ||
108 | { | ||
109 | model: AccountModel.unscoped(), | ||
110 | include: [ | ||
111 | { | ||
112 | attributes: { | ||
113 | exclude: unusedActorAttributesForAPI | ||
114 | }, | ||
115 | model: ActorModel, // Default scope includes avatar and server | ||
116 | required: true | ||
117 | } | ||
118 | ] | ||
119 | } | ||
120 | ] | ||
121 | }, | ||
122 | [ScopeNames.WITH_IN_REPLY_TO]: { | 62 | [ScopeNames.WITH_IN_REPLY_TO]: { |
123 | include: [ | 63 | include: [ |
124 | { | 64 | { |
@@ -319,93 +259,19 @@ export class VideoCommentModel extends Model<Partial<AttributesOnly<VideoComment | |||
319 | searchAccount?: string | 259 | searchAccount?: string |
320 | searchVideo?: string | 260 | searchVideo?: string |
321 | }) { | 261 | }) { |
322 | const { start, count, sort, isLocal, search, searchAccount, searchVideo, onLocalVideo } = parameters | 262 | const queryOptions: ListVideoCommentsOptions = { |
323 | 263 | ...pick(parameters, [ 'start', 'count', 'sort', 'isLocal', 'search', 'searchVideo', 'searchAccount', 'onLocalVideo' ]), | |
324 | const where: WhereOptions = { | ||
325 | deletedAt: null | ||
326 | } | ||
327 | 264 | ||
328 | const whereAccount: WhereOptions = {} | 265 | selectType: 'api', |
329 | const whereActor: WhereOptions = {} | 266 | notDeleted: true |
330 | const whereVideo: WhereOptions = {} | ||
331 | |||
332 | if (isLocal === true) { | ||
333 | Object.assign(whereActor, { | ||
334 | serverId: null | ||
335 | }) | ||
336 | } else if (isLocal === false) { | ||
337 | Object.assign(whereActor, { | ||
338 | serverId: { | ||
339 | [Op.ne]: null | ||
340 | } | ||
341 | }) | ||
342 | } | ||
343 | |||
344 | if (search) { | ||
345 | Object.assign(where, { | ||
346 | [Op.or]: [ | ||
347 | searchAttribute(search, 'text'), | ||
348 | searchAttribute(search, '$Account.Actor.preferredUsername$'), | ||
349 | searchAttribute(search, '$Account.name$'), | ||
350 | searchAttribute(search, '$Video.name$') | ||
351 | ] | ||
352 | }) | ||
353 | } | ||
354 | |||
355 | if (searchAccount) { | ||
356 | Object.assign(whereActor, { | ||
357 | [Op.or]: [ | ||
358 | searchAttribute(searchAccount, '$Account.Actor.preferredUsername$'), | ||
359 | searchAttribute(searchAccount, '$Account.name$') | ||
360 | ] | ||
361 | }) | ||
362 | } | ||
363 | |||
364 | if (searchVideo) { | ||
365 | Object.assign(whereVideo, searchAttribute(searchVideo, 'name')) | ||
366 | } | ||
367 | |||
368 | if (exists(onLocalVideo)) { | ||
369 | Object.assign(whereVideo, { remote: !onLocalVideo }) | ||
370 | } | ||
371 | |||
372 | const getQuery = (forCount: boolean) => { | ||
373 | return { | ||
374 | offset: start, | ||
375 | limit: count, | ||
376 | order: getCommentSort(sort), | ||
377 | where, | ||
378 | include: [ | ||
379 | { | ||
380 | model: AccountModel.unscoped(), | ||
381 | required: true, | ||
382 | where: whereAccount, | ||
383 | include: [ | ||
384 | { | ||
385 | attributes: { | ||
386 | exclude: unusedActorAttributesForAPI | ||
387 | }, | ||
388 | model: forCount === true | ||
389 | ? ActorModel.unscoped() // Default scope includes avatar and server | ||
390 | : ActorModel, | ||
391 | required: true, | ||
392 | where: whereActor | ||
393 | } | ||
394 | ] | ||
395 | }, | ||
396 | { | ||
397 | model: VideoModel.unscoped(), | ||
398 | required: true, | ||
399 | where: whereVideo | ||
400 | } | ||
401 | ] | ||
402 | } | ||
403 | } | 267 | } |
404 | 268 | ||
405 | return Promise.all([ | 269 | return Promise.all([ |
406 | VideoCommentModel.count(getQuery(true)), | 270 | new VideoCommentListQueryBuilder(VideoCommentModel.sequelize, queryOptions).listComments<MCommentAdminFormattable>(), |
407 | VideoCommentModel.findAll(getQuery(false)) | 271 | new VideoCommentListQueryBuilder(VideoCommentModel.sequelize, queryOptions).countComments() |
408 | ]).then(([ total, data ]) => ({ total, data })) | 272 | ]).then(([ rows, count ]) => { |
273 | return { total: count, data: rows } | ||
274 | }) | ||
409 | } | 275 | } |
410 | 276 | ||
411 | static async listThreadsForApi (parameters: { | 277 | static async listThreadsForApi (parameters: { |
@@ -416,67 +282,40 @@ export class VideoCommentModel extends Model<Partial<AttributesOnly<VideoComment | |||
416 | sort: string | 282 | sort: string |
417 | user?: MUserAccountId | 283 | user?: MUserAccountId |
418 | }) { | 284 | }) { |
419 | const { videoId, isVideoOwned, start, count, sort, user } = parameters | 285 | const { videoId, user } = parameters |
420 | 286 | ||
421 | const blockerAccountIds = await VideoCommentModel.buildBlockerAccountIds({ videoId, user, isVideoOwned }) | 287 | const blockerAccountIds = await VideoCommentModel.buildBlockerAccountIds({ user }) |
422 | 288 | ||
423 | const accountBlockedWhere = { | 289 | const commonOptions: ListVideoCommentsOptions = { |
424 | accountId: { | 290 | selectType: 'api', |
425 | [Op.notIn]: Sequelize.literal( | 291 | videoId, |
426 | '(' + buildBlockedAccountSQL(blockerAccountIds) + ')' | 292 | blockerAccountIds |
427 | ) | ||
428 | } | ||
429 | } | 293 | } |
430 | 294 | ||
431 | const queryList = { | 295 | const listOptions: ListVideoCommentsOptions = { |
432 | offset: start, | 296 | ...commonOptions, |
433 | limit: count, | 297 | ...pick(parameters, [ 'sort', 'start', 'count' ]), |
434 | order: getCommentSort(sort), | 298 | |
435 | where: { | 299 | isThread: true, |
436 | [Op.and]: [ | 300 | includeReplyCounters: true |
437 | { | ||
438 | videoId | ||
439 | }, | ||
440 | { | ||
441 | inReplyToCommentId: null | ||
442 | }, | ||
443 | { | ||
444 | [Op.or]: [ | ||
445 | accountBlockedWhere, | ||
446 | { | ||
447 | accountId: null | ||
448 | } | ||
449 | ] | ||
450 | } | ||
451 | ] | ||
452 | } | ||
453 | } | 301 | } |
454 | 302 | ||
455 | const findScopesList: (string | ScopeOptions)[] = [ | 303 | const countOptions: ListVideoCommentsOptions = { |
456 | ScopeNames.WITH_ACCOUNT_FOR_API, | 304 | ...commonOptions, |
457 | { | ||
458 | method: [ ScopeNames.ATTRIBUTES_FOR_API, blockerAccountIds ] | ||
459 | } | ||
460 | ] | ||
461 | 305 | ||
462 | const countScopesList: ScopeOptions[] = [ | 306 | isThread: true |
463 | { | 307 | } |
464 | method: [ ScopeNames.ATTRIBUTES_FOR_API, blockerAccountIds ] | ||
465 | } | ||
466 | ] | ||
467 | 308 | ||
468 | const notDeletedQueryCount = { | 309 | const notDeletedCountOptions: ListVideoCommentsOptions = { |
469 | where: { | 310 | ...commonOptions, |
470 | videoId, | 311 | |
471 | deletedAt: null, | 312 | notDeleted: true |
472 | ...accountBlockedWhere | ||
473 | } | ||
474 | } | 313 | } |
475 | 314 | ||
476 | return Promise.all([ | 315 | return Promise.all([ |
477 | VideoCommentModel.scope(findScopesList).findAll(queryList), | 316 | new VideoCommentListQueryBuilder(VideoCommentModel.sequelize, listOptions).listComments<MCommentAdminFormattable>(), |
478 | VideoCommentModel.scope(countScopesList).count(queryList), | 317 | new VideoCommentListQueryBuilder(VideoCommentModel.sequelize, countOptions).countComments(), |
479 | VideoCommentModel.count(notDeletedQueryCount) | 318 | new VideoCommentListQueryBuilder(VideoCommentModel.sequelize, notDeletedCountOptions).countComments() |
480 | ]).then(([ rows, count, totalNotDeletedComments ]) => { | 319 | ]).then(([ rows, count, totalNotDeletedComments ]) => { |
481 | return { total: count, data: rows, totalNotDeletedComments } | 320 | return { total: count, data: rows, totalNotDeletedComments } |
482 | }) | 321 | }) |
@@ -484,54 +323,29 @@ export class VideoCommentModel extends Model<Partial<AttributesOnly<VideoComment | |||
484 | 323 | ||
485 | static async listThreadCommentsForApi (parameters: { | 324 | static async listThreadCommentsForApi (parameters: { |
486 | videoId: number | 325 | videoId: number |
487 | isVideoOwned: boolean | ||
488 | threadId: number | 326 | threadId: number |
489 | user?: MUserAccountId | 327 | user?: MUserAccountId |
490 | }) { | 328 | }) { |
491 | const { videoId, threadId, user, isVideoOwned } = parameters | 329 | const { user } = parameters |
492 | 330 | ||
493 | const blockerAccountIds = await VideoCommentModel.buildBlockerAccountIds({ videoId, user, isVideoOwned }) | 331 | const blockerAccountIds = await VideoCommentModel.buildBlockerAccountIds({ user }) |
494 | 332 | ||
495 | const query = { | 333 | const queryOptions: ListVideoCommentsOptions = { |
496 | order: [ [ 'createdAt', 'ASC' ], [ 'updatedAt', 'ASC' ] ] as Order, | 334 | ...pick(parameters, [ 'videoId', 'threadId' ]), |
497 | where: { | ||
498 | videoId, | ||
499 | [Op.and]: [ | ||
500 | { | ||
501 | [Op.or]: [ | ||
502 | { id: threadId }, | ||
503 | { originCommentId: threadId } | ||
504 | ] | ||
505 | }, | ||
506 | { | ||
507 | [Op.or]: [ | ||
508 | { | ||
509 | accountId: { | ||
510 | [Op.notIn]: Sequelize.literal( | ||
511 | '(' + buildBlockedAccountSQL(blockerAccountIds) + ')' | ||
512 | ) | ||
513 | } | ||
514 | }, | ||
515 | { | ||
516 | accountId: null | ||
517 | } | ||
518 | ] | ||
519 | } | ||
520 | ] | ||
521 | } | ||
522 | } | ||
523 | 335 | ||
524 | const scopes: any[] = [ | 336 | selectType: 'api', |
525 | ScopeNames.WITH_ACCOUNT_FOR_API, | 337 | sort: 'createdAt', |
526 | { | 338 | |
527 | method: [ ScopeNames.ATTRIBUTES_FOR_API, blockerAccountIds ] | 339 | blockerAccountIds, |
528 | } | 340 | includeReplyCounters: true |
529 | ] | 341 | } |
530 | 342 | ||
531 | return Promise.all([ | 343 | return Promise.all([ |
532 | VideoCommentModel.count(query), | 344 | new VideoCommentListQueryBuilder(VideoCommentModel.sequelize, queryOptions).listComments<MCommentAdminFormattable>(), |
533 | VideoCommentModel.scope(scopes).findAll(query) | 345 | new VideoCommentListQueryBuilder(VideoCommentModel.sequelize, queryOptions).countComments() |
534 | ]).then(([ total, data ]) => ({ total, data })) | 346 | ]).then(([ rows, count ]) => { |
347 | return { total: count, data: rows } | ||
348 | }) | ||
535 | } | 349 | } |
536 | 350 | ||
537 | static listThreadParentComments (comment: MCommentId, t: Transaction, order: 'ASC' | 'DESC' = 'ASC'): Promise<MCommentOwner[]> { | 351 | static listThreadParentComments (comment: MCommentId, t: Transaction, order: 'ASC' | 'DESC' = 'ASC'): Promise<MCommentOwner[]> { |
@@ -559,31 +373,31 @@ export class VideoCommentModel extends Model<Partial<AttributesOnly<VideoComment | |||
559 | .findAll(query) | 373 | .findAll(query) |
560 | } | 374 | } |
561 | 375 | ||
562 | static async listAndCountByVideoForAP (video: MVideoImmutable, start: number, count: number, t?: Transaction) { | 376 | static async listAndCountByVideoForAP (parameters: { |
563 | const blockerAccountIds = await VideoCommentModel.buildBlockerAccountIds({ | 377 | video: MVideoImmutable |
378 | start: number | ||
379 | count: number | ||
380 | }) { | ||
381 | const { video } = parameters | ||
382 | |||
383 | const blockerAccountIds = await VideoCommentModel.buildBlockerAccountIds({ user: null }) | ||
384 | |||
385 | const queryOptions: ListVideoCommentsOptions = { | ||
386 | ...pick(parameters, [ 'start', 'count' ]), | ||
387 | |||
388 | selectType: 'comment-only', | ||
564 | videoId: video.id, | 389 | videoId: video.id, |
565 | isVideoOwned: video.isOwned() | 390 | sort: 'createdAt', |
566 | }) | ||
567 | 391 | ||
568 | const query = { | 392 | blockerAccountIds |
569 | order: [ [ 'createdAt', 'ASC' ] ] as Order, | ||
570 | offset: start, | ||
571 | limit: count, | ||
572 | where: { | ||
573 | videoId: video.id, | ||
574 | accountId: { | ||
575 | [Op.notIn]: Sequelize.literal( | ||
576 | '(' + buildBlockedAccountSQL(blockerAccountIds) + ')' | ||
577 | ) | ||
578 | } | ||
579 | }, | ||
580 | transaction: t | ||
581 | } | 393 | } |
582 | 394 | ||
583 | return Promise.all([ | 395 | return Promise.all([ |
584 | VideoCommentModel.count(query), | 396 | new VideoCommentListQueryBuilder(VideoCommentModel.sequelize, queryOptions).listComments<MComment>(), |
585 | VideoCommentModel.findAll<MComment>(query) | 397 | new VideoCommentListQueryBuilder(VideoCommentModel.sequelize, queryOptions).countComments() |
586 | ]).then(([ total, data ]) => ({ total, data })) | 398 | ]).then(([ rows, count ]) => { |
399 | return { total: count, data: rows } | ||
400 | }) | ||
587 | } | 401 | } |
588 | 402 | ||
589 | static async listForFeed (parameters: { | 403 | static async listForFeed (parameters: { |
@@ -592,97 +406,36 @@ export class VideoCommentModel extends Model<Partial<AttributesOnly<VideoComment | |||
592 | videoId?: number | 406 | videoId?: number |
593 | accountId?: number | 407 | accountId?: number |
594 | videoChannelId?: number | 408 | videoChannelId?: number |
595 | }): Promise<MCommentOwnerVideoFeed[]> { | 409 | }) { |
596 | const serverActor = await getServerActor() | 410 | const blockerAccountIds = await VideoCommentModel.buildBlockerAccountIds({ user: null }) |
597 | const { start, count, videoId, accountId, videoChannelId } = parameters | ||
598 | 411 | ||
599 | const whereAnd: WhereOptions[] = buildBlockedAccountSQLOptimized( | 412 | const queryOptions: ListVideoCommentsOptions = { |
600 | '"VideoCommentModel"."accountId"', | 413 | ...pick(parameters, [ 'start', 'count', 'accountId', 'videoId', 'videoChannelId' ]), |
601 | [ serverActor.Account.id, '"Video->VideoChannel"."accountId"' ] | ||
602 | ) | ||
603 | 414 | ||
604 | if (accountId) { | 415 | selectType: 'feed', |
605 | whereAnd.push({ | ||
606 | accountId | ||
607 | }) | ||
608 | } | ||
609 | 416 | ||
610 | const accountWhere = { | 417 | sort: '-createdAt', |
611 | [Op.and]: whereAnd | 418 | onPublicVideo: true, |
612 | } | 419 | notDeleted: true, |
613 | |||
614 | const videoChannelWhere = videoChannelId ? { id: videoChannelId } : undefined | ||
615 | 420 | ||
616 | const query = { | 421 | blockerAccountIds |
617 | order: [ [ 'createdAt', 'DESC' ] ] as Order, | ||
618 | offset: start, | ||
619 | limit: count, | ||
620 | where: { | ||
621 | deletedAt: null, | ||
622 | accountId: accountWhere | ||
623 | }, | ||
624 | include: [ | ||
625 | { | ||
626 | attributes: [ 'name', 'uuid' ], | ||
627 | model: VideoModel.unscoped(), | ||
628 | required: true, | ||
629 | where: { | ||
630 | privacy: VideoPrivacy.PUBLIC | ||
631 | }, | ||
632 | include: [ | ||
633 | { | ||
634 | attributes: [ 'accountId' ], | ||
635 | model: VideoChannelModel.unscoped(), | ||
636 | required: true, | ||
637 | where: videoChannelWhere | ||
638 | } | ||
639 | ] | ||
640 | } | ||
641 | ] | ||
642 | } | 422 | } |
643 | 423 | ||
644 | if (videoId) query.where['videoId'] = videoId | 424 | return new VideoCommentListQueryBuilder(VideoCommentModel.sequelize, queryOptions).listComments<MCommentOwnerVideoFeed>() |
645 | |||
646 | return VideoCommentModel | ||
647 | .scope([ ScopeNames.WITH_ACCOUNT ]) | ||
648 | .findAll(query) | ||
649 | } | 425 | } |
650 | 426 | ||
651 | static listForBulkDelete (ofAccount: MAccount, filter: { onVideosOfAccount?: MAccountId } = {}) { | 427 | static listForBulkDelete (ofAccount: MAccount, filter: { onVideosOfAccount?: MAccountId } = {}) { |
652 | const accountWhere = filter.onVideosOfAccount | 428 | const queryOptions: ListVideoCommentsOptions = { |
653 | ? { id: filter.onVideosOfAccount.id } | 429 | selectType: 'comment-only', |
654 | : {} | ||
655 | 430 | ||
656 | const query = { | 431 | accountId: ofAccount.id, |
657 | limit: 1000, | 432 | videoAccountOwnerId: filter.onVideosOfAccount?.id, |
658 | where: { | 433 | |
659 | deletedAt: null, | 434 | notDeleted: true, |
660 | accountId: ofAccount.id | 435 | count: 5000 |
661 | }, | ||
662 | include: [ | ||
663 | { | ||
664 | model: VideoModel, | ||
665 | required: true, | ||
666 | include: [ | ||
667 | { | ||
668 | model: VideoChannelModel, | ||
669 | required: true, | ||
670 | include: [ | ||
671 | { | ||
672 | model: AccountModel, | ||
673 | required: true, | ||
674 | where: accountWhere | ||
675 | } | ||
676 | ] | ||
677 | } | ||
678 | ] | ||
679 | } | ||
680 | ] | ||
681 | } | 436 | } |
682 | 437 | ||
683 | return VideoCommentModel | 438 | return new VideoCommentListQueryBuilder(VideoCommentModel.sequelize, queryOptions).listComments<MComment>() |
684 | .scope([ ScopeNames.WITH_ACCOUNT ]) | ||
685 | .findAll(query) | ||
686 | } | 439 | } |
687 | 440 | ||
688 | static async getStats () { | 441 | static async getStats () { |
@@ -750,9 +503,7 @@ export class VideoCommentModel extends Model<Partial<AttributesOnly<VideoComment | |||
750 | } | 503 | } |
751 | 504 | ||
752 | isOwned () { | 505 | isOwned () { |
753 | if (!this.Account) { | 506 | if (!this.Account) return false |
754 | return false | ||
755 | } | ||
756 | 507 | ||
757 | return this.Account.isOwned() | 508 | return this.Account.isOwned() |
758 | } | 509 | } |
@@ -906,22 +657,15 @@ export class VideoCommentModel extends Model<Partial<AttributesOnly<VideoComment | |||
906 | } | 657 | } |
907 | 658 | ||
908 | private static async buildBlockerAccountIds (options: { | 659 | private static async buildBlockerAccountIds (options: { |
909 | videoId: number | 660 | user: MUserAccountId |
910 | isVideoOwned: boolean | 661 | }): Promise<number[]> { |
911 | user?: MUserAccountId | 662 | const { user } = options |
912 | }) { | ||
913 | const { videoId, user, isVideoOwned } = options | ||
914 | 663 | ||
915 | const serverActor = await getServerActor() | 664 | const serverActor = await getServerActor() |
916 | const blockerAccountIds = [ serverActor.Account.id ] | 665 | const blockerAccountIds = [ serverActor.Account.id ] |
917 | 666 | ||
918 | if (user) blockerAccountIds.push(user.Account.id) | 667 | if (user) blockerAccountIds.push(user.Account.id) |
919 | 668 | ||
920 | if (isVideoOwned) { | ||
921 | const videoOwnerAccount = await AccountModel.loadAccountIdFromVideo(videoId) | ||
922 | if (videoOwnerAccount) blockerAccountIds.push(videoOwnerAccount.id) | ||
923 | } | ||
924 | |||
925 | return blockerAccountIds | 669 | return blockerAccountIds |
926 | } | 670 | } |
927 | } | 671 | } |