diff options
-rw-r--r-- | client/src/app/videos/+video-watch/video-watch.component.ts | 31 | ||||
-rw-r--r-- | client/src/app/videos/shared/video.service.ts | 6 | ||||
-rw-r--r-- | server/controllers/api/videos/index.ts | 28 | ||||
-rw-r--r-- | server/tests/api/multiple-servers.ts | 33 | ||||
-rw-r--r-- | server/tests/api/single-server.ts | 5 | ||||
-rw-r--r-- | server/tests/utils/videos.ts | 10 |
6 files changed, 75 insertions, 38 deletions
diff --git a/client/src/app/videos/+video-watch/video-watch.component.ts b/client/src/app/videos/+video-watch/video-watch.component.ts index 2a7290cbd..b26f3092f 100644 --- a/client/src/app/videos/+video-watch/video-watch.component.ts +++ b/client/src/app/videos/+video-watch/video-watch.component.ts | |||
@@ -1,22 +1,18 @@ | |||
1 | import { Component, ElementRef, OnDestroy, OnInit, ViewChild } from '@angular/core' | 1 | import { Component, ElementRef, OnDestroy, OnInit, ViewChild } from '@angular/core' |
2 | import { ActivatedRoute, Router } from '@angular/router' | 2 | import { ActivatedRoute, Router } from '@angular/router' |
3 | import { MetaService } from '@ngx-meta/core' | ||
4 | import { NotificationsService } from 'angular2-notifications' | ||
3 | import { Observable } from 'rxjs/Observable' | 5 | import { Observable } from 'rxjs/Observable' |
4 | import { Subscription } from 'rxjs/Subscription' | 6 | import { Subscription } from 'rxjs/Subscription' |
5 | |||
6 | import videojs from 'video.js' | 7 | import videojs from 'video.js' |
8 | import { UserVideoRateType, VideoRateType } from '../../../../../shared' | ||
7 | import '../../../assets/player/peertube-videojs-plugin' | 9 | import '../../../assets/player/peertube-videojs-plugin' |
8 | |||
9 | import { MetaService } from '@ngx-meta/core' | ||
10 | import { NotificationsService } from 'angular2-notifications' | ||
11 | |||
12 | import { AuthService, ConfirmService } from '../../core' | 10 | import { AuthService, ConfirmService } from '../../core' |
11 | import { VideoBlacklistService } from '../../shared' | ||
12 | import { MarkdownService, VideoDetails, VideoService } from '../shared' | ||
13 | import { VideoDownloadComponent } from './video-download.component' | 13 | import { VideoDownloadComponent } from './video-download.component' |
14 | import { VideoShareComponent } from './video-share.component' | ||
15 | import { VideoReportComponent } from './video-report.component' | 14 | import { VideoReportComponent } from './video-report.component' |
16 | import { VideoDetails, VideoService, MarkdownService } from '../shared' | 15 | import { VideoShareComponent } from './video-share.component' |
17 | import { VideoBlacklistService } from '../../shared' | ||
18 | import { UserVideoRateType, VideoRateType } from '../../../../../shared' | ||
19 | import { BehaviorSubject } from 'rxjs/BehaviorSubject' | ||
20 | 16 | ||
21 | @Component({ | 17 | @Component({ |
22 | selector: 'my-video-watch', | 18 | selector: 'my-video-watch', |
@@ -320,6 +316,8 @@ export class VideoWatchComponent implements OnInit, OnDestroy { | |||
320 | 316 | ||
321 | this.setOpenGraphTags() | 317 | this.setOpenGraphTags() |
322 | this.checkUserRating() | 318 | this.checkUserRating() |
319 | |||
320 | this.prepareViewAdd() | ||
323 | } | 321 | } |
324 | ) | 322 | ) |
325 | } | 323 | } |
@@ -360,4 +358,17 @@ export class VideoWatchComponent implements OnInit, OnDestroy { | |||
360 | this.metaService.setTag('og:url', window.location.href) | 358 | this.metaService.setTag('og:url', window.location.href) |
361 | this.metaService.setTag('url', window.location.href) | 359 | this.metaService.setTag('url', window.location.href) |
362 | } | 360 | } |
361 | |||
362 | private prepareViewAdd () { | ||
363 | // After 30 seconds (or 3/4 of the video), increment add a view | ||
364 | let viewTimeoutSeconds = 30 | ||
365 | if (this.video.duration < viewTimeoutSeconds) viewTimeoutSeconds = (this.video.duration * 3) / 4 | ||
366 | |||
367 | setTimeout(() => { | ||
368 | this.videoService | ||
369 | .viewVideo(this.video.uuid) | ||
370 | .subscribe() | ||
371 | |||
372 | }, viewTimeoutSeconds * 1000) | ||
373 | } | ||
363 | } | 374 | } |
diff --git a/client/src/app/videos/shared/video.service.ts b/client/src/app/videos/shared/video.service.ts index b1ab5f8b9..5d25a26d4 100644 --- a/client/src/app/videos/shared/video.service.ts +++ b/client/src/app/videos/shared/video.service.ts | |||
@@ -41,6 +41,12 @@ export class VideoService { | |||
41 | .catch((res) => this.restExtractor.handleError(res)) | 41 | .catch((res) => this.restExtractor.handleError(res)) |
42 | } | 42 | } |
43 | 43 | ||
44 | viewVideo (uuid: string): Observable<VideoDetails> { | ||
45 | return this.authHttp.post(VideoService.BASE_VIDEO_URL + uuid + '/views', {}) | ||
46 | .map(this.restExtractor.extractDataBool) | ||
47 | .catch(this.restExtractor.handleError) | ||
48 | } | ||
49 | |||
44 | updateVideo (video: VideoEdit) { | 50 | updateVideo (video: VideoEdit) { |
45 | const language = video.language ? video.language : null | 51 | const language = video.language ? video.language : null |
46 | 52 | ||
diff --git a/server/controllers/api/videos/index.ts b/server/controllers/api/videos/index.ts index 244d91914..e2798830e 100644 --- a/server/controllers/api/videos/index.ts +++ b/server/controllers/api/videos/index.ts | |||
@@ -104,6 +104,10 @@ videosRouter.get('/:id', | |||
104 | asyncMiddleware(videosGetValidator), | 104 | asyncMiddleware(videosGetValidator), |
105 | getVideo | 105 | getVideo |
106 | ) | 106 | ) |
107 | videosRouter.post('/:id/views', | ||
108 | asyncMiddleware(videosGetValidator), | ||
109 | asyncMiddleware(viewVideo) | ||
110 | ) | ||
107 | 111 | ||
108 | videosRouter.delete('/:id', | 112 | videosRouter.delete('/:id', |
109 | authenticate, | 113 | authenticate, |
@@ -311,25 +315,25 @@ async function updateVideo (req: express.Request, res: express.Response) { | |||
311 | } | 315 | } |
312 | } | 316 | } |
313 | 317 | ||
314 | async function getVideo (req: express.Request, res: express.Response) { | 318 | function getVideo (req: express.Request, res: express.Response) { |
319 | const videoInstance = res.locals.video | ||
320 | |||
321 | return res.json(videoInstance.toFormattedDetailsJSON()) | ||
322 | } | ||
323 | |||
324 | async function viewVideo (req: express.Request, res: express.Response) { | ||
315 | const videoInstance = res.locals.video | 325 | const videoInstance = res.locals.video |
316 | 326 | ||
317 | const baseIncrementPromise = videoInstance.increment('views') | 327 | await videoInstance.increment('views') |
318 | .then(() => getServerAccount()) | 328 | const serverAccount = await getServerAccount() |
319 | 329 | ||
320 | if (videoInstance.isOwned()) { | 330 | if (videoInstance.isOwned()) { |
321 | // The increment is done directly in the database, not using the instance value | 331 | await sendCreateViewToVideoFollowers(serverAccount, videoInstance, undefined) |
322 | baseIncrementPromise | ||
323 | .then(serverAccount => sendCreateViewToVideoFollowers(serverAccount, videoInstance, undefined)) | ||
324 | .catch(err => logger.error('Cannot add view to video/send view to followers for %s.', videoInstance.uuid, err)) | ||
325 | } else { | 332 | } else { |
326 | baseIncrementPromise | 333 | await sendCreateViewToOrigin(serverAccount, videoInstance, undefined) |
327 | .then(serverAccount => sendCreateViewToOrigin(serverAccount, videoInstance, undefined)) | ||
328 | .catch(err => logger.error('Cannot send view to origin server for %s.', videoInstance.uuid, err)) | ||
329 | } | 334 | } |
330 | 335 | ||
331 | // Do not wait the view system | 336 | return res.status(204).end() |
332 | return res.json(videoInstance.toFormattedDetailsJSON()) | ||
333 | } | 337 | } |
334 | 338 | ||
335 | async function getVideoDescription (req: express.Request, res: express.Response) { | 339 | async function getVideoDescription (req: express.Request, res: express.Response) { |
diff --git a/server/tests/api/multiple-servers.ts b/server/tests/api/multiple-servers.ts index 052b0231f..c80ded862 100644 --- a/server/tests/api/multiple-servers.ts +++ b/server/tests/api/multiple-servers.ts | |||
@@ -25,6 +25,7 @@ import { | |||
25 | doubleFollow | 25 | doubleFollow |
26 | } from '../utils' | 26 | } from '../utils' |
27 | import { createUser } from '../utils/users' | 27 | import { createUser } from '../utils/users' |
28 | import { viewVideo } from '../utils/videos' | ||
28 | 29 | ||
29 | const expect = chai.expect | 30 | const expect = chai.expect |
30 | 31 | ||
@@ -486,10 +487,10 @@ describe('Test multiple servers', function () { | |||
486 | this.timeout(10000) | 487 | this.timeout(10000) |
487 | 488 | ||
488 | const tasks: Promise<any>[] = [] | 489 | const tasks: Promise<any>[] = [] |
489 | tasks.push(getVideo(servers[2].url, localVideosServer3[0])) | 490 | tasks.push(viewVideo(servers[2].url, localVideosServer3[0])) |
490 | tasks.push(getVideo(servers[2].url, localVideosServer3[0])) | 491 | tasks.push(viewVideo(servers[2].url, localVideosServer3[0])) |
491 | tasks.push(getVideo(servers[2].url, localVideosServer3[0])) | 492 | tasks.push(viewVideo(servers[2].url, localVideosServer3[0])) |
492 | tasks.push(getVideo(servers[2].url, localVideosServer3[1])) | 493 | tasks.push(viewVideo(servers[2].url, localVideosServer3[1])) |
493 | 494 | ||
494 | await Promise.all(tasks) | 495 | await Promise.all(tasks) |
495 | 496 | ||
@@ -502,8 +503,8 @@ describe('Test multiple servers', function () { | |||
502 | const video0 = videos.find(v => v.uuid === localVideosServer3[0]) | 503 | const video0 = videos.find(v => v.uuid === localVideosServer3[0]) |
503 | const video1 = videos.find(v => v.uuid === localVideosServer3[1]) | 504 | const video1 = videos.find(v => v.uuid === localVideosServer3[1]) |
504 | 505 | ||
505 | expect(video0.views).to.equal(7) | 506 | expect(video0.views).to.equal(3) |
506 | expect(video1.views).to.equal(5) | 507 | expect(video1.views).to.equal(1) |
507 | } | 508 | } |
508 | }) | 509 | }) |
509 | 510 | ||
@@ -511,16 +512,16 @@ describe('Test multiple servers', function () { | |||
511 | this.timeout(15000) | 512 | this.timeout(15000) |
512 | 513 | ||
513 | const tasks: Promise<any>[] = [] | 514 | const tasks: Promise<any>[] = [] |
514 | tasks.push(getVideo(servers[0].url, remoteVideosServer1[0])) | 515 | tasks.push(viewVideo(servers[0].url, remoteVideosServer1[0])) |
515 | tasks.push(getVideo(servers[1].url, remoteVideosServer2[0])) | 516 | tasks.push(viewVideo(servers[1].url, remoteVideosServer2[0])) |
516 | tasks.push(getVideo(servers[1].url, remoteVideosServer2[0])) | 517 | tasks.push(viewVideo(servers[1].url, remoteVideosServer2[0])) |
517 | tasks.push(getVideo(servers[2].url, remoteVideosServer3[0])) | 518 | tasks.push(viewVideo(servers[2].url, remoteVideosServer3[0])) |
518 | tasks.push(getVideo(servers[2].url, remoteVideosServer3[1])) | 519 | tasks.push(viewVideo(servers[2].url, remoteVideosServer3[1])) |
519 | tasks.push(getVideo(servers[2].url, remoteVideosServer3[1])) | 520 | tasks.push(viewVideo(servers[2].url, remoteVideosServer3[1])) |
520 | tasks.push(getVideo(servers[2].url, remoteVideosServer3[1])) | 521 | tasks.push(viewVideo(servers[2].url, remoteVideosServer3[1])) |
521 | tasks.push(getVideo(servers[2].url, localVideosServer3[1])) | 522 | tasks.push(viewVideo(servers[2].url, localVideosServer3[1])) |
522 | tasks.push(getVideo(servers[2].url, localVideosServer3[1])) | 523 | tasks.push(viewVideo(servers[2].url, localVideosServer3[1])) |
523 | tasks.push(getVideo(servers[2].url, localVideosServer3[1])) | 524 | tasks.push(viewVideo(servers[2].url, localVideosServer3[1])) |
524 | 525 | ||
525 | await Promise.all(tasks) | 526 | await Promise.all(tasks) |
526 | 527 | ||
diff --git a/server/tests/api/single-server.ts b/server/tests/api/single-server.ts index 40e2c64fe..041d13225 100644 --- a/server/tests/api/single-server.ts +++ b/server/tests/api/single-server.ts | |||
@@ -33,6 +33,7 @@ import { | |||
33 | searchVideoWithSort, | 33 | searchVideoWithSort, |
34 | updateVideo | 34 | updateVideo |
35 | } from '../utils' | 35 | } from '../utils' |
36 | import { viewVideo } from '../utils/videos' | ||
36 | 37 | ||
37 | describe('Test a single server', function () { | 38 | describe('Test a single server', function () { |
38 | let server: ServerInfo = null | 39 | let server: ServerInfo = null |
@@ -214,6 +215,10 @@ describe('Test a single server', function () { | |||
214 | }) | 215 | }) |
215 | 216 | ||
216 | it('Should have the views updated', async function () { | 217 | it('Should have the views updated', async function () { |
218 | await viewVideo(server.url, videoId) | ||
219 | await viewVideo(server.url, videoId) | ||
220 | await viewVideo(server.url, videoId) | ||
221 | |||
217 | const res = await getVideo(server.url, videoId) | 222 | const res = await getVideo(server.url, videoId) |
218 | 223 | ||
219 | const video = res.body | 224 | const video = res.body |
diff --git a/server/tests/utils/videos.ts b/server/tests/utils/videos.ts index dababe924..73a9f1a0a 100644 --- a/server/tests/utils/videos.ts +++ b/server/tests/utils/videos.ts | |||
@@ -55,6 +55,15 @@ function getVideo (url: string, id: number | string, expectedStatus = 200) { | |||
55 | .expect(expectedStatus) | 55 | .expect(expectedStatus) |
56 | } | 56 | } |
57 | 57 | ||
58 | function viewVideo (url: string, id: number | string, expectedStatus = 204) { | ||
59 | const path = '/api/v1/videos/' + id + '/views' | ||
60 | |||
61 | return request(url) | ||
62 | .post(path) | ||
63 | .set('Accept', 'application/json') | ||
64 | .expect(expectedStatus) | ||
65 | } | ||
66 | |||
58 | function getVideoWithToken (url: string, token: string, id: number | string, expectedStatus = 200) { | 67 | function getVideoWithToken (url: string, token: string, id: number | string, expectedStatus = 200) { |
59 | const path = '/api/v1/videos/' + id | 68 | const path = '/api/v1/videos/' + id |
60 | 69 | ||
@@ -313,5 +322,6 @@ export { | |||
313 | uploadVideo, | 322 | uploadVideo, |
314 | updateVideo, | 323 | updateVideo, |
315 | rateVideo, | 324 | rateVideo, |
325 | viewVideo, | ||
316 | parseTorrentVideo | 326 | parseTorrentVideo |
317 | } | 327 | } |