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