]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blob - server/lib/activitypub/videos/updater.ts
Move AP video channel creation
[github/Chocobozzz/PeerTube.git] / server / lib / activitypub / videos / updater.ts
1 import { Transaction } from 'sequelize/types'
2 import { resetSequelizeInstance } from '@server/helpers/database-utils'
3 import { logger } from '@server/helpers/logger'
4 import { sequelizeTypescript } from '@server/initializers/database'
5 import { Notifier } from '@server/lib/notifier'
6 import { PeerTubeSocket } from '@server/lib/peertube-socket'
7 import { autoBlacklistVideoIfNeeded } from '@server/lib/video-blacklist'
8 import { VideoCaptionModel } from '@server/models/video/video-caption'
9 import { VideoLiveModel } from '@server/models/video/video-live'
10 import { MActor, MChannelAccountLight, MChannelId, MVideoAccountLightBlacklistAllFiles, MVideoFullLight } from '@server/types/models'
11 import { VideoObject, VideoPrivacy } from '@shared/models'
12 import { APVideoAbstractBuilder, getVideoAttributesFromObject } from './shared'
13
14 export class APVideoUpdater extends APVideoAbstractBuilder {
15 private readonly wasPrivateVideo: boolean
16 private readonly wasUnlistedVideo: boolean
17
18 private readonly videoFieldsSave: any
19
20 private readonly oldVideoChannel: MChannelAccountLight
21
22 constructor (
23 protected readonly videoObject: VideoObject,
24 private readonly video: MVideoAccountLightBlacklistAllFiles
25 ) {
26 super()
27
28 this.wasPrivateVideo = this.video.privacy === VideoPrivacy.PRIVATE
29 this.wasUnlistedVideo = this.video.privacy === VideoPrivacy.UNLISTED
30
31 this.oldVideoChannel = this.video.VideoChannel
32
33 this.videoFieldsSave = this.video.toJSON()
34 }
35
36 async update (overrideTo?: string[]) {
37 logger.debug('Updating remote video "%s".', this.videoObject.uuid, { videoObject: this.videoObject })
38
39 try {
40 const channelActor = await this.getOrCreateVideoChannelFromVideoObject()
41
42 const thumbnailModel = await this.tryToGenerateThumbnail(this.video)
43
44 const videoUpdated = await sequelizeTypescript.transaction(async t => {
45 this.checkChannelUpdateOrThrow(channelActor)
46
47 const videoUpdated = await this.updateVideo(channelActor.VideoChannel, t, overrideTo)
48
49 if (thumbnailModel) await videoUpdated.addAndSaveThumbnail(thumbnailModel, t)
50
51 await this.setPreview(videoUpdated, t)
52 await this.setWebTorrentFiles(videoUpdated, t)
53 await this.setStreamingPlaylists(videoUpdated, t)
54 await this.setTags(videoUpdated, t)
55 await this.setTrackers(videoUpdated, t)
56 await this.setCaptions(videoUpdated, t)
57 await this.setOrDeleteLive(videoUpdated, t)
58
59 return videoUpdated
60 })
61
62 await autoBlacklistVideoIfNeeded({
63 video: videoUpdated,
64 user: undefined,
65 isRemote: true,
66 isNew: false,
67 transaction: undefined
68 })
69
70 // Notify our users?
71 if (this.wasPrivateVideo || this.wasUnlistedVideo) {
72 Notifier.Instance.notifyOnNewVideoIfNeeded(videoUpdated)
73 }
74
75 if (videoUpdated.isLive) {
76 PeerTubeSocket.Instance.sendVideoLiveNewState(videoUpdated)
77 PeerTubeSocket.Instance.sendVideoViewsUpdate(videoUpdated)
78 }
79
80 logger.info('Remote video with uuid %s updated', this.videoObject.uuid)
81
82 return videoUpdated
83 } catch (err) {
84 this.catchUpdateError(err)
85 }
86 }
87
88 // Check we can update the channel: we trust the remote server
89 private checkChannelUpdateOrThrow (newChannelActor: MActor) {
90 if (!this.oldVideoChannel.Actor.serverId || !newChannelActor.serverId) {
91 throw new Error('Cannot check old channel/new channel validity because `serverId` is null')
92 }
93
94 if (this.oldVideoChannel.Actor.serverId !== newChannelActor.serverId) {
95 throw new Error(`New channel ${newChannelActor.url} is not on the same server than new channel ${this.oldVideoChannel.Actor.url}`)
96 }
97 }
98
99 private updateVideo (channel: MChannelId, transaction: Transaction, overrideTo?: string[]) {
100 const to = overrideTo || this.videoObject.to
101 const videoData = getVideoAttributesFromObject(channel, this.videoObject, to)
102 this.video.name = videoData.name
103 this.video.uuid = videoData.uuid
104 this.video.url = videoData.url
105 this.video.category = videoData.category
106 this.video.licence = videoData.licence
107 this.video.language = videoData.language
108 this.video.description = videoData.description
109 this.video.support = videoData.support
110 this.video.nsfw = videoData.nsfw
111 this.video.commentsEnabled = videoData.commentsEnabled
112 this.video.downloadEnabled = videoData.downloadEnabled
113 this.video.waitTranscoding = videoData.waitTranscoding
114 this.video.state = videoData.state
115 this.video.duration = videoData.duration
116 this.video.createdAt = videoData.createdAt
117 this.video.publishedAt = videoData.publishedAt
118 this.video.originallyPublishedAt = videoData.originallyPublishedAt
119 this.video.privacy = videoData.privacy
120 this.video.channelId = videoData.channelId
121 this.video.views = videoData.views
122 this.video.isLive = videoData.isLive
123
124 // Ensures we update the updated video attribute
125 this.video.changed('updatedAt', true)
126
127 return this.video.save({ transaction }) as Promise<MVideoFullLight>
128 }
129
130 private async setCaptions (videoUpdated: MVideoFullLight, t: Transaction) {
131 await VideoCaptionModel.deleteAllCaptionsOfRemoteVideo(videoUpdated.id, t)
132
133 await this.insertOrReplaceCaptions(videoUpdated, t)
134 }
135
136 private async setOrDeleteLive (videoUpdated: MVideoFullLight, transaction: Transaction) {
137 if (this.video.isLive) return this.insertOrReplaceLive(videoUpdated, transaction)
138
139 // Delete existing live if it exists
140 await VideoLiveModel.destroy({
141 where: {
142 videoId: this.video.id
143 },
144 transaction
145 })
146
147 videoUpdated.VideoLive = null
148 }
149
150 private catchUpdateError (err: Error) {
151 if (this.video !== undefined && this.videoFieldsSave !== undefined) {
152 resetSequelizeInstance(this.video, this.videoFieldsSave)
153 }
154
155 // This is just a debug because we will retry the insert
156 logger.debug('Cannot update the remote video.', { err })
157 throw err
158 }
159 }