]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blob - 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
1 import { expect } from 'chai'
2 import { FIXTURE_URLS } from '@server/tests/shared'
3 import { areHttpImportTestsDisabled } from '@shared/core-utils'
4 import { HttpStatusCode, VideoChannelSyncState, VideoInclude, VideoPrivacy } from '@shared/models'
5 import {
6 createMultipleServers,
7 getServerImportConfig,
8 killallServers,
9 PeerTubeServer,
10 setAccessTokensToServers,
11 setDefaultAccountAvatar,
12 setDefaultChannelAvatar,
13 setDefaultVideoChannel,
14 waitJobs
15 } from '@shared/server-commands'
16
17 describe('Test channel synchronizations', function () {
18 if (areHttpImportTestsDisabled()) return
19
20 function runSuite (mode: 'youtube-dl' | 'yt-dlp') {
21
22 describe('Sync using ' + mode, function () {
23 let servers: PeerTubeServer[]
24
25 let startTestDate: Date
26
27 let rootChannelSyncId: number
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) {
37 await servers[0].sql.updateQuery(
38 `UPDATE "videoChannelSync" ` +
39 `SET "createdAt"='${newDate}', "lastSyncAt"='${newDate}' ` +
40 `WHERE id=${channelSyncId}`
41 )
42 }
43
44 before(async function () {
45 this.timeout(240_000)
46
47 startTestDate = new Date()
48
49 servers = await createMultipleServers(2, getServerImportConfig(mode))
50
51 await setAccessTokensToServers(servers)
52 await setDefaultVideoChannel(servers)
53 await setDefaultChannelAvatar(servers)
54 await setDefaultAccountAvatar(servers)
55
56 await servers[0].config.enableChannelSync()
57
58 {
59 userInfo.accessToken = await servers[0].users.generateUserAndToken(userInfo.username)
60
61 const { videoChannels } = await servers[0].users.getMyInfo({ token: userInfo.accessToken })
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 {
70 const { video } = await servers[0].imports.importVideo({
71 attributes: {
72 channelId: servers[0].store.channel.id,
73 privacy: VideoPrivacy.PUBLIC,
74 targetUrl: FIXTURE_URLS.youtube
75 }
76 })
77
78 expect(video.name).to.equal('small video - youtube')
79
80 const { total } = await servers[0].videos.listByChannel({ handle: 'root_channel', include: VideoInclude.NOT_PUBLISHED_STATE })
81 expect(total).to.equal(1)
82 }
83
84 const { videoChannelSync } = await servers[0].channelSyncs.create({
85 attributes: {
86 externalChannelUrl: FIXTURE_URLS.youtubeChannel,
87 videoChannelId: servers[0].store.channel.id
88 },
89 token: servers[0].accessToken,
90 expectedStatus: HttpStatusCode.OK_200
91 })
92 rootChannelSyncId = videoChannelSync.id
93
94 // Ensure any missing video not already fetched will be considered as new
95 await changeDateForSync(videoChannelSync.id, '1970-01-01')
96
97 await servers[0].debug.sendCommand({
98 body: {
99 command: 'process-video-channel-sync-latest'
100 }
101 })
102
103 {
104 await waitJobs(servers)
105
106 const { total, data } = await servers[0].videos.listByChannel({
107 handle: 'root_channel',
108 include: VideoInclude.NOT_PUBLISHED_STATE
109 })
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
118 const { videoChannelSync } = await servers[0].channelSyncs.create({
119 attributes: {
120 externalChannelUrl,
121 videoChannelId: servers[0].store.channel.id
122 },
123 token: servers[0].accessToken,
124 expectedStatus: HttpStatusCode.OK_200
125 })
126
127 expect(videoChannelSync.externalChannelUrl).to.equal(externalChannelUrl)
128 expect(videoChannelSync.channel).to.include({
129 id: servers[0].store.channel.id,
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 () {
137 const { videoChannelSync } = await servers[0].channelSyncs.create({
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 () {
148 await waitJobs(servers)
149
150 const { data } = await servers[0].channelSyncs.listByAccount({ accountName: userInfo.username })
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
163 await servers[0].debug.sendCommand({
164 body: {
165 command: 'process-video-channel-sync-latest'
166 }
167 })
168
169 await waitJobs(servers)
170
171 const { data, total } = await servers[0].videos.listByChannel({
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 {
183 const { total, data } = await servers[0].channelSyncs.listByAccount({ accountName: 'root' })
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
196 expect(data[0].channel).to.contain({ id: servers[0].store.channel.id })
197 expect(data[1]).to.contain({ externalChannelUrl: FIXTURE_URLS.youtubeChannel + '?foo=bar' })
198 }
199
200 // User
201 {
202 const { total, data } = await servers[0].channelSyncs.listByAccount({ accountName: userInfo.username })
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
214 it('Should list imports of a channel synchronization', async function () {
215 const { total, data } = await servers[0].imports.getMyVideoImports({ videoChannelSyncId: rootChannelSyncId })
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
222 it('Should remove user\'s channel synchronizations', async function () {
223 await servers[0].channelSyncs.delete({ channelSyncId: userInfo.syncId })
224
225 const { total } = await servers[0].channelSyncs.listByAccount({ accountName: userInfo.username })
226 expect(total).to.equal(0)
227 })
228
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
283 after(async function () {
284 await killallServers(servers)
285 })
286 })
287 }
288
289 runSuite('youtube-dl')
290 runSuite('yt-dlp')
291 })