diff options
Diffstat (limited to 'server/models/video')
-rw-r--r-- | server/models/video/video.ts | 92 |
1 files changed, 65 insertions, 27 deletions
diff --git a/server/models/video/video.ts b/server/models/video/video.ts index 2ad9c00dd..7ababbf23 100644 --- a/server/models/video/video.ts +++ b/server/models/video/video.ts | |||
@@ -95,7 +95,14 @@ enum ScopeNames { | |||
95 | } | 95 | } |
96 | 96 | ||
97 | @Scopes({ | 97 | @Scopes({ |
98 | [ScopeNames.AVAILABLE_FOR_LIST]: (actorId: number, hideNSFW: boolean, filter?: VideoFilter, withFiles?: boolean, accountId?: number) => { | 98 | [ScopeNames.AVAILABLE_FOR_LIST]: (options: { |
99 | actorId: number, | ||
100 | hideNSFW: boolean, | ||
101 | filter?: VideoFilter, | ||
102 | withFiles?: boolean, | ||
103 | accountId?: number, | ||
104 | videoChannelId?: number | ||
105 | }) => { | ||
99 | const accountInclude = { | 106 | const accountInclude = { |
100 | attributes: [ 'name' ], | 107 | attributes: [ 'name' ], |
101 | model: AccountModel.unscoped(), | 108 | model: AccountModel.unscoped(), |
@@ -106,7 +113,7 @@ enum ScopeNames { | |||
106 | attributes: [ 'preferredUsername', 'url', 'serverId', 'avatarId' ], | 113 | attributes: [ 'preferredUsername', 'url', 'serverId', 'avatarId' ], |
107 | model: ActorModel.unscoped(), | 114 | model: ActorModel.unscoped(), |
108 | required: true, | 115 | required: true, |
109 | where: VideoModel.buildActorWhereWithFilter(filter), | 116 | where: VideoModel.buildActorWhereWithFilter(options.filter), |
110 | include: [ | 117 | include: [ |
111 | { | 118 | { |
112 | attributes: [ 'host' ], | 119 | attributes: [ 'host' ], |
@@ -122,6 +129,18 @@ enum ScopeNames { | |||
122 | ] | 129 | ] |
123 | } | 130 | } |
124 | 131 | ||
132 | const videoChannelInclude = { | ||
133 | attributes: [ 'name', 'description' ], | ||
134 | model: VideoChannelModel.unscoped(), | ||
135 | required: true, | ||
136 | where: {}, | ||
137 | include: [ | ||
138 | accountInclude | ||
139 | ] | ||
140 | } | ||
141 | |||
142 | // Force actorId to be a number to avoid SQL injections | ||
143 | const actorIdNumber = parseInt(options.actorId.toString(), 10) | ||
125 | const query: IFindOptions<VideoModel> = { | 144 | const query: IFindOptions<VideoModel> = { |
126 | where: { | 145 | where: { |
127 | id: { | 146 | id: { |
@@ -132,32 +151,23 @@ enum ScopeNames { | |||
132 | '(' + | 151 | '(' + |
133 | 'SELECT "videoShare"."videoId" AS "id" FROM "videoShare" ' + | 152 | 'SELECT "videoShare"."videoId" AS "id" FROM "videoShare" ' + |
134 | 'INNER JOIN "actorFollow" ON "actorFollow"."targetActorId" = "videoShare"."actorId" ' + | 153 | 'INNER JOIN "actorFollow" ON "actorFollow"."targetActorId" = "videoShare"."actorId" ' + |
135 | 'WHERE "actorFollow"."actorId" = ' + parseInt(actorId.toString(), 10) + | 154 | 'WHERE "actorFollow"."actorId" = ' + actorIdNumber + |
136 | ' UNION ' + | 155 | ' UNION ' + |
137 | 'SELECT "video"."id" AS "id" FROM "video" ' + | 156 | 'SELECT "video"."id" AS "id" FROM "video" ' + |
138 | 'INNER JOIN "videoChannel" ON "videoChannel"."id" = "video"."channelId" ' + | 157 | 'INNER JOIN "videoChannel" ON "videoChannel"."id" = "video"."channelId" ' + |
139 | 'INNER JOIN "account" ON "account"."id" = "videoChannel"."accountId" ' + | 158 | 'INNER JOIN "account" ON "account"."id" = "videoChannel"."accountId" ' + |
140 | 'INNER JOIN "actor" ON "account"."actorId" = "actor"."id" ' + | 159 | 'INNER JOIN "actor" ON "account"."actorId" = "actor"."id" ' + |
141 | 'LEFT JOIN "actorFollow" ON "actorFollow"."targetActorId" = "actor"."id" ' + | 160 | 'LEFT JOIN "actorFollow" ON "actorFollow"."targetActorId" = "actor"."id" ' + |
142 | 'WHERE "actor"."serverId" IS NULL OR "actorFollow"."actorId" = ' + parseInt(actorId.toString(), 10) + | 161 | 'WHERE "actor"."serverId" IS NULL OR "actorFollow"."actorId" = ' + actorIdNumber + |
143 | ')' | 162 | ')' |
144 | ) | 163 | ) |
145 | }, | 164 | }, |
146 | privacy: VideoPrivacy.PUBLIC | 165 | privacy: VideoPrivacy.PUBLIC |
147 | }, | 166 | }, |
148 | include: [ | 167 | include: [ videoChannelInclude ] |
149 | { | ||
150 | attributes: [ 'name', 'description' ], | ||
151 | model: VideoChannelModel.unscoped(), | ||
152 | required: true, | ||
153 | include: [ | ||
154 | accountInclude | ||
155 | ] | ||
156 | } | ||
157 | ] | ||
158 | } | 168 | } |
159 | 169 | ||
160 | if (withFiles === true) { | 170 | if (options.withFiles === true) { |
161 | query.include.push({ | 171 | query.include.push({ |
162 | model: VideoFileModel.unscoped(), | 172 | model: VideoFileModel.unscoped(), |
163 | required: true | 173 | required: true |
@@ -165,13 +175,19 @@ enum ScopeNames { | |||
165 | } | 175 | } |
166 | 176 | ||
167 | // Hide nsfw videos? | 177 | // Hide nsfw videos? |
168 | if (hideNSFW === true) { | 178 | if (options.hideNSFW === true) { |
169 | query.where['nsfw'] = false | 179 | query.where['nsfw'] = false |
170 | } | 180 | } |
171 | 181 | ||
172 | if (accountId) { | 182 | if (options.accountId) { |
173 | accountInclude.where = { | 183 | accountInclude.where = { |
174 | id: accountId | 184 | id: options.accountId |
185 | } | ||
186 | } | ||
187 | |||
188 | if (options.videoChannelId) { | ||
189 | videoChannelInclude.where = { | ||
190 | id: options.videoChannelId | ||
175 | } | 191 | } |
176 | } | 192 | } |
177 | 193 | ||
@@ -697,23 +713,37 @@ export class VideoModel extends Model<VideoModel> { | |||
697 | }) | 713 | }) |
698 | } | 714 | } |
699 | 715 | ||
700 | static async listForApi ( | 716 | static async listForApi (options: { |
701 | start: number, | 717 | start: number, |
702 | count: number, | 718 | count: number, |
703 | sort: string, | 719 | sort: string, |
704 | hideNSFW: boolean, | 720 | hideNSFW: boolean, |
721 | withFiles: boolean, | ||
705 | filter?: VideoFilter, | 722 | filter?: VideoFilter, |
706 | withFiles = false, | 723 | accountId?: number, |
707 | accountId?: number | 724 | videoChannelId?: number |
708 | ) { | 725 | }) { |
709 | const query = { | 726 | const query = { |
710 | offset: start, | 727 | offset: options.start, |
711 | limit: count, | 728 | limit: options.count, |
712 | order: getSort(sort) | 729 | order: getSort(options.sort) |
713 | } | 730 | } |
714 | 731 | ||
715 | const serverActor = await getServerActor() | 732 | const serverActor = await getServerActor() |
716 | return VideoModel.scope({ method: [ ScopeNames.AVAILABLE_FOR_LIST, serverActor.id, hideNSFW, filter, withFiles, accountId ] }) | 733 | const scopes = { |
734 | method: [ | ||
735 | ScopeNames.AVAILABLE_FOR_LIST, { | ||
736 | actorId: serverActor.id, | ||
737 | hideNSFW: options.hideNSFW, | ||
738 | filter: options.filter, | ||
739 | withFiles: options.withFiles, | ||
740 | accountId: options.accountId, | ||
741 | videoChannelId: options.videoChannelId | ||
742 | } | ||
743 | ] | ||
744 | } | ||
745 | |||
746 | return VideoModel.scope(scopes) | ||
717 | .findAndCountAll(query) | 747 | .findAndCountAll(query) |
718 | .then(({ rows, count }) => { | 748 | .then(({ rows, count }) => { |
719 | return { | 749 | return { |
@@ -750,8 +780,16 @@ export class VideoModel extends Model<VideoModel> { | |||
750 | } | 780 | } |
751 | 781 | ||
752 | const serverActor = await getServerActor() | 782 | const serverActor = await getServerActor() |
783 | const scopes = { | ||
784 | method: [ | ||
785 | ScopeNames.AVAILABLE_FOR_LIST, { | ||
786 | actorId: serverActor.id, | ||
787 | hideNSFW | ||
788 | } | ||
789 | ] | ||
790 | } | ||
753 | 791 | ||
754 | return VideoModel.scope({ method: [ ScopeNames.AVAILABLE_FOR_LIST, serverActor.id, hideNSFW ] }) | 792 | return VideoModel.scope(scopes) |
755 | .findAndCountAll(query) | 793 | .findAndCountAll(query) |
756 | .then(({ rows, count }) => { | 794 | .then(({ rows, count }) => { |
757 | return { | 795 | return { |