]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - server/tests/api/videos/video-channel-syncs.ts
Fix sync import of latest videos
[github/Chocobozzz/PeerTube.git] / server / tests / api / videos / video-channel-syncs.ts
CommitLineData
2a491182
F
1import { expect } from 'chai'
2import { FIXTURE_URLS } from '@server/tests/shared'
3import { areHttpImportTestsDisabled } from '@shared/core-utils'
4import { HttpStatusCode, VideoChannelSyncState, VideoInclude, VideoPrivacy } from '@shared/models'
5import {
3204f4d1 6 createMultipleServers,
2a491182 7 getServerImportConfig,
3204f4d1 8 killallServers,
2a491182
F
9 PeerTubeServer,
10 setAccessTokensToServers,
11 setDefaultAccountAvatar,
12 setDefaultChannelAvatar,
13 setDefaultVideoChannel,
14 waitJobs
15} from '@shared/server-commands'
16
17describe('Test channel synchronizations', function () {
18 if (areHttpImportTestsDisabled()) return
19
20 function runSuite (mode: 'youtube-dl' | 'yt-dlp') {
21
22 describe('Sync using ' + mode, function () {
3204f4d1 23 let servers: PeerTubeServer[]
a3b472a1 24
2a491182 25 let startTestDate: Date
a3b472a1
C
26
27 let rootChannelSyncId: number
2a491182
F
28 const userInfo = {
29 accessToken: '',
30 username: 'user1',
31 channelName: 'user1_channel',
32 channelId: -1,
33 syncId: -1
34 }
35
36 async function changeDateForSync (channelSyncId: number, newDate: string) {
3204f4d1 37 await servers[0].sql.updateQuery(
2a491182
F
38 `UPDATE "videoChannelSync" ` +
39 `SET "createdAt"='${newDate}', "lastSyncAt"='${newDate}' ` +
40 `WHERE id=${channelSyncId}`
41 )
42 }
43
44 before(async function () {
3204f4d1 45 this.timeout(240_000)
2a491182
F
46
47 startTestDate = new Date()
48
3204f4d1 49 servers = await createMultipleServers(2, getServerImportConfig(mode))
2a491182 50
3204f4d1
C
51 await setAccessTokensToServers(servers)
52 await setDefaultVideoChannel(servers)
53 await setDefaultChannelAvatar(servers)
54 await setDefaultAccountAvatar(servers)
2a491182 55
3204f4d1 56 await servers[0].config.enableChannelSync()
2a491182
F
57
58 {
3204f4d1 59 userInfo.accessToken = await servers[0].users.generateUserAndToken(userInfo.username)
2a491182 60
3204f4d1 61 const { videoChannels } = await servers[0].users.getMyInfo({ token: userInfo.accessToken })
2a491182
F
62 userInfo.channelId = videoChannels[0].id
63 }
64 })
65
66 it('Should fetch the latest channel videos of a remote channel', async function () {
67 this.timeout(120_000)
68
69 {
3204f4d1 70 const { video } = await servers[0].imports.importVideo({
2a491182 71 attributes: {
3204f4d1 72 channelId: servers[0].store.channel.id,
2a491182
F
73 privacy: VideoPrivacy.PUBLIC,
74 targetUrl: FIXTURE_URLS.youtube
75 }
76 })
77
78 expect(video.name).to.equal('small video - youtube')
79
3204f4d1 80 const { total } = await servers[0].videos.listByChannel({ handle: 'root_channel', include: VideoInclude.NOT_PUBLISHED_STATE })
2a491182
F
81 expect(total).to.equal(1)
82 }
83
3204f4d1 84 const { videoChannelSync } = await servers[0].channelSyncs.create({
2a491182
F
85 attributes: {
86 externalChannelUrl: FIXTURE_URLS.youtubeChannel,
3204f4d1 87 videoChannelId: servers[0].store.channel.id
2a491182 88 },
3204f4d1 89 token: servers[0].accessToken,
2a491182
F
90 expectedStatus: HttpStatusCode.OK_200
91 })
a3b472a1 92 rootChannelSyncId = videoChannelSync.id
2a491182
F
93
94 // Ensure any missing video not already fetched will be considered as new
95 await changeDateForSync(videoChannelSync.id, '1970-01-01')
96
3204f4d1 97 await servers[0].debug.sendCommand({
2a491182
F
98 body: {
99 command: 'process-video-channel-sync-latest'
100 }
101 })
102
103 {
3204f4d1 104 await waitJobs(servers)
2a491182 105
3204f4d1
C
106 const { total, data } = await servers[0].videos.listByChannel({
107 handle: 'root_channel',
108 include: VideoInclude.NOT_PUBLISHED_STATE
109 })
2a491182
F
110 expect(total).to.equal(2)
111 expect(data[0].name).to.equal('test')
112 }
113 })
114
115 it('Should add another synchronization', async function () {
116 const externalChannelUrl = FIXTURE_URLS.youtubeChannel + '?foo=bar'
117
3204f4d1 118 const { videoChannelSync } = await servers[0].channelSyncs.create({
2a491182
F
119 attributes: {
120 externalChannelUrl,
3204f4d1 121 videoChannelId: servers[0].store.channel.id
2a491182 122 },
3204f4d1 123 token: servers[0].accessToken,
2a491182
F
124 expectedStatus: HttpStatusCode.OK_200
125 })
126
127 expect(videoChannelSync.externalChannelUrl).to.equal(externalChannelUrl)
128 expect(videoChannelSync.channel).to.include({
3204f4d1 129 id: servers[0].store.channel.id,
2a491182
F
130 name: 'root_channel'
131 })
132 expect(videoChannelSync.state.id).to.equal(VideoChannelSyncState.WAITING_FIRST_RUN)
133 expect(new Date(videoChannelSync.createdAt)).to.be.above(startTestDate).and.to.be.at.most(new Date())
134 })
135
136 it('Should add a synchronization for another user', async function () {
3204f4d1 137 const { videoChannelSync } = await servers[0].channelSyncs.create({
2a491182
F
138 attributes: {
139 externalChannelUrl: FIXTURE_URLS.youtubeChannel + '?baz=qux',
140 videoChannelId: userInfo.channelId
141 },
142 token: userInfo.accessToken
143 })
144 userInfo.syncId = videoChannelSync.id
145 })
146
147 it('Should not import a channel if not asked', async function () {
3204f4d1 148 await waitJobs(servers)
2a491182 149
3204f4d1 150 const { data } = await servers[0].channelSyncs.listByAccount({ accountName: userInfo.username })
2a491182
F
151
152 expect(data[0].state).to.contain({
153 id: VideoChannelSyncState.WAITING_FIRST_RUN,
154 label: 'Waiting first run'
155 })
156 })
157
158 it('Should only fetch the videos newer than the creation date', async function () {
159 this.timeout(120_000)
160
161 await changeDateForSync(userInfo.syncId, '2019-03-01')
162
3204f4d1 163 await servers[0].debug.sendCommand({
2a491182
F
164 body: {
165 command: 'process-video-channel-sync-latest'
166 }
167 })
168
3204f4d1 169 await waitJobs(servers)
2a491182 170
3204f4d1 171 const { data, total } = await servers[0].videos.listByChannel({
2a491182
F
172 handle: userInfo.channelName,
173 include: VideoInclude.NOT_PUBLISHED_STATE
174 })
175
176 expect(total).to.equal(1)
177 expect(data[0].name).to.equal('test')
178 })
179
180 it('Should list channel synchronizations', async function () {
181 // Root
182 {
3204f4d1 183 const { total, data } = await servers[0].channelSyncs.listByAccount({ accountName: 'root' })
2a491182
F
184 expect(total).to.equal(2)
185
186 expect(data[0]).to.deep.contain({
187 externalChannelUrl: FIXTURE_URLS.youtubeChannel,
188 state: {
189 id: VideoChannelSyncState.SYNCED,
190 label: 'Synchronized'
191 }
192 })
193
194 expect(new Date(data[0].lastSyncAt)).to.be.greaterThan(startTestDate)
195
3204f4d1 196 expect(data[0].channel).to.contain({ id: servers[0].store.channel.id })
2a491182
F
197 expect(data[1]).to.contain({ externalChannelUrl: FIXTURE_URLS.youtubeChannel + '?foo=bar' })
198 }
199
200 // User
201 {
3204f4d1 202 const { total, data } = await servers[0].channelSyncs.listByAccount({ accountName: userInfo.username })
2a491182
F
203 expect(total).to.equal(1)
204 expect(data[0]).to.deep.contain({
205 externalChannelUrl: FIXTURE_URLS.youtubeChannel + '?baz=qux',
206 state: {
207 id: VideoChannelSyncState.SYNCED,
208 label: 'Synchronized'
209 }
210 })
211 }
212 })
213
a3b472a1 214 it('Should list imports of a channel synchronization', async function () {
3204f4d1 215 const { total, data } = await servers[0].imports.getMyVideoImports({ videoChannelSyncId: rootChannelSyncId })
a3b472a1
C
216
217 expect(total).to.equal(1)
218 expect(data).to.have.lengthOf(1)
219 expect(data[0].video.name).to.equal('test')
220 })
221
2a491182 222 it('Should remove user\'s channel synchronizations', async function () {
3204f4d1 223 await servers[0].channelSyncs.delete({ channelSyncId: userInfo.syncId })
2a491182 224
3204f4d1 225 const { total } = await servers[0].channelSyncs.listByAccount({ accountName: userInfo.username })
2a491182
F
226 expect(total).to.equal(0)
227 })
228
3204f4d1
C
229 // FIXME: youtube-dl doesn't work when speicifying a port after the hostname
230 // it('Should import a remote PeerTube channel', async function () {
231 // this.timeout(240_000)
232
233 // await servers[1].videos.quickUpload({ name: 'remote 1' })
234 // await waitJobs(servers)
235
236 // const { videoChannelSync } = await servers[0].channelSyncs.create({
237 // attributes: {
238 // externalChannelUrl: servers[1].url + '/c/root_channel',
239 // videoChannelId: userInfo.channelId
240 // },
241 // token: userInfo.accessToken
242 // })
243 // await servers[0].channels.importVideos({
244 // channelName: userInfo.channelName,
245 // externalChannelUrl: servers[1].url + '/c/root_channel',
246 // videoChannelSyncId: videoChannelSync.id,
247 // token: userInfo.accessToken
248 // })
249
250 // await waitJobs(servers)
251
252 // const { data, total } = await servers[0].videos.listByChannel({
253 // handle: userInfo.channelName,
254 // include: VideoInclude.NOT_PUBLISHED_STATE
255 // })
256
257 // expect(total).to.equal(2)
258 // expect(data[0].name).to.equal('remote 1')
259 // })
260
261 // it('Should keep synced a remote PeerTube channel', async function () {
262 // this.timeout(240_000)
263
264 // await servers[1].videos.quickUpload({ name: 'remote 2' })
265 // await waitJobs(servers)
266
267 // await servers[0].debug.sendCommand({
268 // body: {
269 // command: 'process-video-channel-sync-latest'
270 // }
271 // })
272
273 // await waitJobs(servers)
274
275 // const { data, total } = await servers[0].videos.listByChannel({
276 // handle: userInfo.channelName,
277 // include: VideoInclude.NOT_PUBLISHED_STATE
278 // })
279 // expect(total).to.equal(2)
280 // expect(data[0].name).to.equal('remote 2')
281 // })
282
2a491182 283 after(async function () {
3204f4d1 284 await killallServers(servers)
2a491182
F
285 })
286 })
287 }
288
289 runSuite('youtube-dl')
290 runSuite('yt-dlp')
291})