diff options
Diffstat (limited to 'server/models/video')
-rw-r--r-- | server/models/video/sql/video/videos-id-list-query-builder.ts | 22 | ||||
-rw-r--r-- | server/models/video/video.ts | 10 |
2 files changed, 30 insertions, 2 deletions
diff --git a/server/models/video/sql/video/videos-id-list-query-builder.ts b/server/models/video/sql/video/videos-id-list-query-builder.ts index 62f1855c7..cba77c1d1 100644 --- a/server/models/video/sql/video/videos-id-list-query-builder.ts +++ b/server/models/video/sql/video/videos-id-list-query-builder.ts | |||
@@ -78,6 +78,8 @@ export type BuildVideosListQueryOptions = { | |||
78 | 78 | ||
79 | transaction?: Transaction | 79 | transaction?: Transaction |
80 | logging?: boolean | 80 | logging?: boolean |
81 | |||
82 | excludeAlreadyWatched?: boolean | ||
81 | } | 83 | } |
82 | 84 | ||
83 | export class VideosIdListQueryBuilder extends AbstractRunQuery { | 85 | export class VideosIdListQueryBuilder extends AbstractRunQuery { |
@@ -260,6 +262,14 @@ export class VideosIdListQueryBuilder extends AbstractRunQuery { | |||
260 | this.whereDurationMax(options.durationMax) | 262 | this.whereDurationMax(options.durationMax) |
261 | } | 263 | } |
262 | 264 | ||
265 | if (options.excludeAlreadyWatched) { | ||
266 | if (exists(options.user.id)) { | ||
267 | this.whereExcludeAlreadyWatched(options.user.id) | ||
268 | } else { | ||
269 | throw new Error('Cannot use excludeAlreadyWatched parameter when auth token is not provided') | ||
270 | } | ||
271 | } | ||
272 | |||
263 | this.whereSearch(options.search) | 273 | this.whereSearch(options.search) |
264 | 274 | ||
265 | if (options.isCount === true) { | 275 | if (options.isCount === true) { |
@@ -598,6 +608,18 @@ export class VideosIdListQueryBuilder extends AbstractRunQuery { | |||
598 | this.replacements.durationMax = durationMax | 608 | this.replacements.durationMax = durationMax |
599 | } | 609 | } |
600 | 610 | ||
611 | private whereExcludeAlreadyWatched (userId: number) { | ||
612 | this.and.push( | ||
613 | 'NOT EXISTS (' + | ||
614 | ' SELECT 1' + | ||
615 | ' FROM "userVideoHistory"' + | ||
616 | ' WHERE "video"."id" = "userVideoHistory"."videoId"' + | ||
617 | ' AND "userVideoHistory"."userId" = :excludeAlreadyWatchedUserId' + | ||
618 | ')' | ||
619 | ) | ||
620 | this.replacements.excludeAlreadyWatchedUserId = userId | ||
621 | } | ||
622 | |||
601 | private groupForTrending (trendingDays: number) { | 623 | private groupForTrending (trendingDays: number) { |
602 | const viewsGteDate = new Date(new Date().getTime() - (24 * 3600 * 1000) * trendingDays) | 624 | const viewsGteDate = new Date(new Date().getTime() - (24 * 3600 * 1000) * trendingDays) |
603 | 625 | ||
diff --git a/server/models/video/video.ts b/server/models/video/video.ts index 0c5ed64ec..f817c4a33 100644 --- a/server/models/video/video.ts +++ b/server/models/video/video.ts | |||
@@ -1086,6 +1086,8 @@ export class VideoModel extends Model<Partial<AttributesOnly<VideoModel>>> { | |||
1086 | countVideos?: boolean | 1086 | countVideos?: boolean |
1087 | 1087 | ||
1088 | search?: string | 1088 | search?: string |
1089 | |||
1090 | excludeAlreadyWatched?: boolean | ||
1089 | }) { | 1091 | }) { |
1090 | VideoModel.throwIfPrivateIncludeWithoutUser(options.include, options.user) | 1092 | VideoModel.throwIfPrivateIncludeWithoutUser(options.include, options.user) |
1091 | VideoModel.throwIfPrivacyOneOfWithoutUser(options.privacyOneOf, options.user) | 1093 | VideoModel.throwIfPrivacyOneOfWithoutUser(options.privacyOneOf, options.user) |
@@ -1124,7 +1126,8 @@ export class VideoModel extends Model<Partial<AttributesOnly<VideoModel>>> { | |||
1124 | 'historyOfUser', | 1126 | 'historyOfUser', |
1125 | 'hasHLSFiles', | 1127 | 'hasHLSFiles', |
1126 | 'hasWebtorrentFiles', | 1128 | 'hasWebtorrentFiles', |
1127 | 'search' | 1129 | 'search', |
1130 | 'excludeAlreadyWatched' | ||
1128 | ]), | 1131 | ]), |
1129 | 1132 | ||
1130 | serverAccountIdForBlock: serverActor.Account.id, | 1133 | serverAccountIdForBlock: serverActor.Account.id, |
@@ -1170,6 +1173,8 @@ export class VideoModel extends Model<Partial<AttributesOnly<VideoModel>>> { | |||
1170 | durationMin?: number // seconds | 1173 | durationMin?: number // seconds |
1171 | durationMax?: number // seconds | 1174 | durationMax?: number // seconds |
1172 | uuids?: string[] | 1175 | uuids?: string[] |
1176 | |||
1177 | excludeAlreadyWatched?: boolean | ||
1173 | }) { | 1178 | }) { |
1174 | VideoModel.throwIfPrivateIncludeWithoutUser(options.include, options.user) | 1179 | VideoModel.throwIfPrivateIncludeWithoutUser(options.include, options.user) |
1175 | VideoModel.throwIfPrivacyOneOfWithoutUser(options.privacyOneOf, options.user) | 1180 | VideoModel.throwIfPrivacyOneOfWithoutUser(options.privacyOneOf, options.user) |
@@ -1203,7 +1208,8 @@ export class VideoModel extends Model<Partial<AttributesOnly<VideoModel>>> { | |||
1203 | 'hasWebtorrentFiles', | 1208 | 'hasWebtorrentFiles', |
1204 | 'uuids', | 1209 | 'uuids', |
1205 | 'search', | 1210 | 'search', |
1206 | 'displayOnlyForFollower' | 1211 | 'displayOnlyForFollower', |
1212 | 'excludeAlreadyWatched' | ||
1207 | ]), | 1213 | ]), |
1208 | serverAccountIdForBlock: serverActor.Account.id | 1214 | serverAccountIdForBlock: serverActor.Account.id |
1209 | } | 1215 | } |