]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blob - client/src/app/shared/shared-main/video/video.model.ts
Merge branch 'master' into release/3.3.0
[github/Chocobozzz/PeerTube.git] / client / src / app / shared / shared-main / video / video.model.ts
1 import { AuthUser } from '@app/core'
2 import { User } from '@app/core/users/user.model'
3 import { durationToString, getAbsoluteAPIUrl, getAbsoluteEmbedUrl } from '@app/helpers'
4 import { Actor } from '@app/shared/shared-main/account/actor.model'
5 import { peertubeTranslate } from '@shared/core-utils/i18n'
6 import {
7 ActorImage,
8 HTMLServerConfig,
9 UserRight,
10 Video as VideoServerModel,
11 VideoConstant,
12 VideoPrivacy,
13 VideoScheduleUpdate,
14 VideoState
15 } from '@shared/models'
16
17 export class Video implements VideoServerModel {
18 byVideoChannel: string
19 byAccount: string
20
21 createdAt: Date
22 updatedAt: Date
23 publishedAt: Date
24 originallyPublishedAt: Date | string
25 category: VideoConstant<number>
26 licence: VideoConstant<number>
27 language: VideoConstant<string>
28 privacy: VideoConstant<VideoPrivacy>
29
30 description: string
31
32 duration: number
33 durationLabel: string
34
35 id: number
36 uuid: string
37 shortUUID: string
38
39 isLocal: boolean
40
41 name: string
42 serverHost: string
43 thumbnailPath: string
44 thumbnailUrl: string
45
46 isLive: boolean
47
48 previewPath: string
49 previewUrl: string
50
51 embedPath: string
52 embedUrl: string
53
54 url?: string
55
56 views: number
57 likes: number
58 dislikes: number
59 nsfw: boolean
60
61 originInstanceUrl: string
62 originInstanceHost: string
63
64 waitTranscoding?: boolean
65 state?: VideoConstant<VideoState>
66 scheduledUpdate?: VideoScheduleUpdate
67 blacklisted?: boolean
68 blockedReason?: string
69
70 account: {
71 id: number
72 name: string
73 displayName: string
74 url: string
75 host: string
76 avatar?: ActorImage
77 }
78
79 channel: {
80 id: number
81 name: string
82 displayName: string
83 url: string
84 host: string
85 avatar?: ActorImage
86 }
87
88 userHistory?: {
89 currentTime: number
90 }
91
92 pluginData?: any
93
94 static buildWatchUrl (video: Partial<Pick<Video, 'uuid' | 'shortUUID'>>) {
95 return '/w/' + (video.shortUUID || video.uuid)
96 }
97
98 static buildUpdateUrl (video: Pick<Video, 'uuid'>) {
99 return '/videos/update/' + video.uuid
100 }
101
102 constructor (hash: VideoServerModel, translations = {}) {
103 const absoluteAPIUrl = getAbsoluteAPIUrl()
104
105 this.createdAt = new Date(hash.createdAt.toString())
106 this.publishedAt = new Date(hash.publishedAt.toString())
107 this.category = hash.category
108 this.licence = hash.licence
109 this.language = hash.language
110 this.privacy = hash.privacy
111 this.waitTranscoding = hash.waitTranscoding
112 this.state = hash.state
113 this.description = hash.description
114
115 this.isLive = hash.isLive
116
117 this.duration = hash.duration
118 this.durationLabel = durationToString(hash.duration)
119
120 this.id = hash.id
121 this.uuid = hash.uuid
122 this.shortUUID = hash.shortUUID
123
124 this.isLocal = hash.isLocal
125 this.name = hash.name
126
127 this.thumbnailPath = hash.thumbnailPath
128 this.thumbnailUrl = this.thumbnailPath
129 ? hash.thumbnailUrl || (absoluteAPIUrl + hash.thumbnailPath)
130 : null
131
132 this.previewPath = hash.previewPath
133 this.previewUrl = this.previewPath
134 ? hash.previewUrl || (absoluteAPIUrl + hash.previewPath)
135 : null
136
137 this.embedPath = hash.embedPath
138 this.embedUrl = hash.embedUrl || (getAbsoluteEmbedUrl() + hash.embedPath)
139
140 this.url = hash.url
141
142 this.views = hash.views
143 this.likes = hash.likes
144 this.dislikes = hash.dislikes
145
146 this.nsfw = hash.nsfw
147
148 this.account = hash.account
149 this.channel = hash.channel
150
151 this.byAccount = Actor.CREATE_BY_STRING(hash.account.name, hash.account.host)
152 this.byVideoChannel = Actor.CREATE_BY_STRING(hash.channel.name, hash.channel.host)
153
154 this.category.label = peertubeTranslate(this.category.label, translations)
155 this.licence.label = peertubeTranslate(this.licence.label, translations)
156 this.language.label = peertubeTranslate(this.language.label, translations)
157 this.privacy.label = peertubeTranslate(this.privacy.label, translations)
158
159 this.scheduledUpdate = hash.scheduledUpdate
160 this.originallyPublishedAt = hash.originallyPublishedAt ? new Date(hash.originallyPublishedAt.toString()) : null
161
162 if (this.state) this.state.label = peertubeTranslate(this.state.label, translations)
163
164 this.blacklisted = hash.blacklisted
165 this.blockedReason = hash.blacklistedReason
166
167 this.userHistory = hash.userHistory
168
169 this.originInstanceHost = this.account.host
170 this.originInstanceUrl = 'https://' + this.originInstanceHost
171
172 this.pluginData = hash.pluginData
173 }
174
175 isVideoNSFWForUser (user: User, serverConfig: HTMLServerConfig) {
176 // Video is not NSFW, skip
177 if (this.nsfw === false) return false
178
179 // Return user setting if logged in
180 if (user) return user.nsfwPolicy !== 'display'
181
182 // Return default instance config
183 return serverConfig.instance.defaultNSFWPolicy !== 'display'
184 }
185
186 isRemovableBy (user: AuthUser) {
187 return user && this.isLocal === true && (this.account.name === user.username || user.hasRight(UserRight.REMOVE_ANY_VIDEO))
188 }
189
190 isBlockableBy (user: AuthUser) {
191 return this.blacklisted !== true && user && user.hasRight(UserRight.MANAGE_VIDEO_BLACKLIST) === true
192 }
193
194 isUnblockableBy (user: AuthUser) {
195 return this.blacklisted === true && user && user.hasRight(UserRight.MANAGE_VIDEO_BLACKLIST) === true
196 }
197
198 isUpdatableBy (user: AuthUser) {
199 return user && this.isLocal === true && (this.account.name === user.username || user.hasRight(UserRight.UPDATE_ANY_VIDEO))
200 }
201
202 isLiveInfoAvailableBy (user: AuthUser) {
203 return this.isLive &&
204 user && this.isLocal === true && (this.account.name === user.username || user.hasRight(UserRight.GET_ANY_LIVE))
205 }
206
207 canBeDuplicatedBy (user: AuthUser) {
208 return user && this.isLocal === false && user.hasRight(UserRight.MANAGE_VIDEOS_REDUNDANCIES)
209 }
210
211 getExactNumberOfViews () {
212 if (this.views < 1000) return ''
213
214 if (this.isLive) {
215 return $localize`${this.views} viewers`
216 }
217
218 return $localize`${this.views} views`
219 }
220 }