+ 'INNER JOIN "actorFollow" ON "actorFollow"."targetActorId" = "actor"."id" ' +
+ 'WHERE "actorFollow"."actorId" = ' + actorIdNumber +
+ localVideosReq +
+ ')'
+ )
+ }
+ })
+ }
+
+ if (options.withFiles === true) {
+ whereAnd.push({
+ id: {
+ [ Op.in ]: Sequelize.literal(
+ '(SELECT "videoId" FROM "videoFile")'
+ )
+ }
+ })
+ }
+
+ // FIXME: issues with sequelize count when making a join on n:m relation, so we just make a IN()
+ if (options.tagsAllOf || options.tagsOneOf) {
+ if (options.tagsOneOf) {
+ whereAnd.push({
+ id: {
+ [ Op.in ]: Sequelize.literal(
+ '(' +
+ 'SELECT "videoId" FROM "videoTag" ' +
+ 'INNER JOIN "tag" ON "tag"."id" = "videoTag"."tagId" ' +
+ 'WHERE "tag"."name" IN (' + createSafeIn(VideoModel, options.tagsOneOf) + ')' +
+ ')'
+ )
+ }
+ })
+ }
+
+ if (options.tagsAllOf) {
+ whereAnd.push({
+ id: {
+ [ Op.in ]: Sequelize.literal(
+ '(' +
+ 'SELECT "videoId" FROM "videoTag" ' +
+ 'INNER JOIN "tag" ON "tag"."id" = "videoTag"."tagId" ' +
+ 'WHERE "tag"."name" IN (' + createSafeIn(VideoModel, options.tagsAllOf) + ')' +
+ 'GROUP BY "videoTag"."videoId" HAVING COUNT(*) = ' + options.tagsAllOf.length +
+ ')'
+ )
+ }
+ })
+ }
+ }
+
+ if (options.nsfw === true || options.nsfw === false) {
+ whereAnd.push({ nsfw: options.nsfw })
+ }
+
+ if (options.categoryOneOf) {
+ whereAnd.push({
+ category: {
+ [ Op.or ]: options.categoryOneOf
+ }
+ })
+ }
+
+ if (options.licenceOneOf) {
+ whereAnd.push({
+ licence: {
+ [ Op.or ]: options.licenceOneOf
+ }
+ })
+ }
+
+ if (options.languageOneOf) {
+ let videoLanguages = options.languageOneOf
+ if (options.languageOneOf.find(l => l === '_unknown')) {
+ videoLanguages = videoLanguages.concat([ null ])
+ }
+
+ whereAnd.push({
+ [Op.or]: [
+ {
+ language: {
+ [ Op.or ]: videoLanguages
+ }
+ },
+ {
+ id: {
+ [ Op.in ]: Sequelize.literal(
+ '(' +
+ 'SELECT "videoId" FROM "videoCaption" ' +
+ 'WHERE "language" IN (' + createSafeIn(VideoModel, options.languageOneOf) + ') ' +
+ ')'
+ )
+ }
+ }
+ ]
+ })
+ }
+
+ if (options.trendingDays) {
+ query.include.push(VideoModel.buildTrendingQuery(options.trendingDays))
+
+ query.subQuery = false
+ }
+
+ if (options.historyOfUser) {
+ query.include.push({
+ model: UserVideoHistoryModel,
+ required: true,
+ where: {
+ userId: options.historyOfUser.id
+ }
+ })
+
+ // Even if the relation is n:m, we know that a user only have 0..1 video history
+ // So we won't have multiple rows for the same video
+ // Without this, we would not be able to sort on "updatedAt" column of UserVideoHistoryModel
+ query.subQuery = false
+ }
+
+ query.where = {
+ [ Op.and ]: whereAnd
+ }
+
+ return query
+ },
+ [ ScopeNames.WITH_THUMBNAILS ]: {
+ include: [
+ {
+ model: ThumbnailModel,
+ required: false
+ }
+ ]
+ },
+ [ ScopeNames.WITH_USER_ID ]: {