From ce33919c24e7402d92d81f3cd8e545df52d98240 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Mon, 6 Aug 2018 17:13:39 +0200 Subject: Import magnets with webtorrent --- .../shared/video-import/video-import.service.ts | 58 +++++---- .../video-import-torrent.component.html | 60 ++++++++++ .../video-import-torrent.component.scss | 37 ++++++ .../video-import-torrent.component.ts | 132 +++++++++++++++++++++ .../video-import-url.component.html | 2 +- .../video-import-url.component.scss | 2 +- .../video-import-url.component.ts | 2 +- .../videos/+video-edit/video-add.component.html | 6 +- .../app/videos/+video-edit/video-add.component.ts | 13 +- .../src/app/videos/+video-edit/video-add.module.ts | 4 +- 10 files changed, 287 insertions(+), 29 deletions(-) create mode 100644 client/src/app/videos/+video-edit/video-add-components/video-import-torrent.component.html create mode 100644 client/src/app/videos/+video-edit/video-add-components/video-import-torrent.component.scss create mode 100644 client/src/app/videos/+video-edit/video-add-components/video-import-torrent.component.ts (limited to 'client') diff --git a/client/src/app/shared/video-import/video-import.service.ts b/client/src/app/shared/video-import/video-import.service.ts index 59b58ab38..002412bd7 100644 --- a/client/src/app/shared/video-import/video-import.service.ts +++ b/client/src/app/shared/video-import/video-import.service.ts @@ -26,8 +26,43 @@ export class VideoImportService { private serverService: ServerService ) {} - importVideo (targetUrl: string, video: VideoUpdate): Observable { + importVideoUrl (targetUrl: string, video: VideoUpdate): Observable { const url = VideoImportService.BASE_VIDEO_IMPORT_URL + + const body = this.buildImportVideoObject(video) + body.targetUrl = targetUrl + + const data = objectToFormData(body) + return this.authHttp.post(url, data) + .pipe(catchError(res => this.restExtractor.handleError(res))) + } + + importVideoTorrent (target: string | Blob, video: VideoUpdate): Observable { + const url = VideoImportService.BASE_VIDEO_IMPORT_URL + const body: VideoImportCreate = this.buildImportVideoObject(video) + + if (typeof target === 'string') body.magnetUri = target + else body.torrentfile = target + + const data = objectToFormData(body) + return this.authHttp.post(url, data) + .pipe(catchError(res => this.restExtractor.handleError(res))) + } + + getMyVideoImports (pagination: RestPagination, sort: SortMeta): Observable> { + let params = new HttpParams() + params = this.restService.addRestGetParams(params, pagination, sort) + + return this.authHttp + .get>(UserService.BASE_USERS_URL + '/me/videos/imports', { params }) + .pipe( + switchMap(res => this.extractVideoImports(res)), + map(res => this.restExtractor.convertResultListDateToHuman(res)), + catchError(err => this.restExtractor.handleError(err)) + ) + } + + private buildImportVideoObject (video: VideoUpdate): VideoImportCreate { const language = video.language || null const licence = video.licence || null const category = video.category || null @@ -35,9 +70,7 @@ export class VideoImportService { const support = video.support || null const scheduleUpdate = video.scheduleUpdate || null - const body: VideoImportCreate = { - targetUrl, - + return { name: video.name, category, licence, @@ -54,23 +87,6 @@ export class VideoImportService { previewfile: video.previewfile, scheduleUpdate } - - const data = objectToFormData(body) - return this.authHttp.post(url, data) - .pipe(catchError(res => this.restExtractor.handleError(res))) - } - - getMyVideoImports (pagination: RestPagination, sort: SortMeta): Observable> { - let params = new HttpParams() - params = this.restService.addRestGetParams(params, pagination, sort) - - return this.authHttp - .get>(UserService.BASE_USERS_URL + '/me/videos/imports', { params }) - .pipe( - switchMap(res => this.extractVideoImports(res)), - map(res => this.restExtractor.convertResultListDateToHuman(res)), - catchError(err => this.restExtractor.handleError(err)) - ) } private extractVideoImports (result: ResultList): Observable> { diff --git a/client/src/app/videos/+video-edit/video-add-components/video-import-torrent.component.html b/client/src/app/videos/+video-edit/video-add-components/video-import-torrent.component.html new file mode 100644 index 000000000..409e4de5e --- /dev/null +++ b/client/src/app/videos/+video-edit/video-add-components/video-import-torrent.component.html @@ -0,0 +1,60 @@ +
+
+
+ +
+ + + + +
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ + +
+
+ +
+ Congratulations, the video will be imported with BitTorrent! You can already add information about this video. +
+ + +
+ + +
+
+ + +
+
+
diff --git a/client/src/app/videos/+video-edit/video-add-components/video-import-torrent.component.scss b/client/src/app/videos/+video-edit/video-add-components/video-import-torrent.component.scss new file mode 100644 index 000000000..1ef5adc25 --- /dev/null +++ b/client/src/app/videos/+video-edit/video-add-components/video-import-torrent.component.scss @@ -0,0 +1,37 @@ +@import 'variables'; +@import 'mixins'; + +$width-size: 190px; + +.peertube-select-container { + @include peertube-select-container($width-size); +} + +.import-video-torrent { + display: flex; + flex-direction: column; + align-items: center; + + .icon.icon-upload { + @include icon(90px); + margin-bottom: 25px; + cursor: default; + + background-image: url('../../../../assets/images/video/upload.svg'); + } + + input[type=text] { + @include peertube-input-text($width-size); + display: block; + } + + input[type=button] { + @include peertube-button; + @include orange-button; + + width: $width-size; + margin-top: 30px; + } +} + + diff --git a/client/src/app/videos/+video-edit/video-add-components/video-import-torrent.component.ts b/client/src/app/videos/+video-edit/video-add-components/video-import-torrent.component.ts new file mode 100644 index 000000000..330c37718 --- /dev/null +++ b/client/src/app/videos/+video-edit/video-add-components/video-import-torrent.component.ts @@ -0,0 +1,132 @@ +import { Component, EventEmitter, OnInit, Output } from '@angular/core' +import { Router } from '@angular/router' +import { NotificationsService } from 'angular2-notifications' +import { VideoPrivacy, VideoUpdate } from '../../../../../../shared/models/videos' +import { AuthService, ServerService } from '../../../core' +import { VideoService } from '../../../shared/video/video.service' +import { I18n } from '@ngx-translate/i18n-polyfill' +import { LoadingBarService } from '@ngx-loading-bar/core' +import { VideoSend } from '@app/videos/+video-edit/video-add-components/video-send' +import { CanComponentDeactivate } from '@app/shared/guards/can-deactivate-guard.service' +import { VideoEdit } from '@app/shared/video/video-edit.model' +import { FormValidatorService } from '@app/shared' +import { VideoCaptionService } from '@app/shared/video-caption' +import { VideoImportService } from '@app/shared/video-import' + +@Component({ + selector: 'my-video-import-torrent', + templateUrl: './video-import-torrent.component.html', + styleUrls: [ + '../shared/video-edit.component.scss', + './video-import-torrent.component.scss' + ] +}) +export class VideoImportTorrentComponent extends VideoSend implements OnInit, CanComponentDeactivate { + @Output() firstStepDone = new EventEmitter() + + videoFileName: string + magnetUri = '' + + isImportingVideo = false + hasImportedVideo = false + isUpdatingVideo = false + + video: VideoEdit + + protected readonly DEFAULT_VIDEO_PRIVACY = VideoPrivacy.PRIVATE + + constructor ( + protected formValidatorService: FormValidatorService, + protected loadingBar: LoadingBarService, + protected notificationsService: NotificationsService, + protected authService: AuthService, + protected serverService: ServerService, + protected videoService: VideoService, + protected videoCaptionService: VideoCaptionService, + private router: Router, + private videoImportService: VideoImportService, + private i18n: I18n + ) { + super() + } + + ngOnInit () { + super.ngOnInit() + } + + canDeactivate () { + return { canDeactivate: true } + } + + isMagnetUrlValid () { + return !!this.magnetUri + } + + importVideo () { + this.isImportingVideo = true + + const videoUpdate: VideoUpdate = { + privacy: this.firstStepPrivacyId, + waitTranscoding: false, + commentsEnabled: true, + channelId: this.firstStepChannelId + } + + this.loadingBar.start() + + this.videoImportService.importVideoTorrent(this.magnetUri, videoUpdate).subscribe( + res => { + this.loadingBar.complete() + this.firstStepDone.emit(res.video.name) + this.isImportingVideo = false + this.hasImportedVideo = true + + this.video = new VideoEdit(Object.assign(res.video, { + commentsEnabled: videoUpdate.commentsEnabled, + support: null, + thumbnailUrl: null, + previewUrl: null + })) + this.hydrateFormFromVideo() + }, + + err => { + this.loadingBar.complete() + this.isImportingVideo = false + this.notificationsService.error(this.i18n('Error'), err.message) + } + ) + } + + updateSecondStep () { + if (this.checkForm() === false) { + return + } + + this.video.patch(this.form.value) + + this.isUpdatingVideo = true + + // Update the video + this.updateVideoAndCaptions(this.video) + .subscribe( + () => { + this.isUpdatingVideo = false + this.notificationsService.success(this.i18n('Success'), this.i18n('Video to import updated.')) + + this.router.navigate([ '/my-account', 'video-imports' ]) + }, + + err => { + this.isUpdatingVideo = false + this.notificationsService.error(this.i18n('Error'), err.message) + console.error(err) + } + ) + + } + + private hydrateFormFromVideo () { + this.form.patchValue(this.video.toFormPatch()) + } +} diff --git a/client/src/app/videos/+video-edit/video-add-components/video-import-url.component.html b/client/src/app/videos/+video-edit/video-add-components/video-import-url.component.html index 6b431f6f6..9f5fc6d22 100644 --- a/client/src/app/videos/+video-edit/video-add-components/video-import-url.component.html +++ b/client/src/app/videos/+video-edit/video-add-components/video-import-url.component.html @@ -1,5 +1,5 @@
-
+
diff --git a/client/src/app/videos/+video-edit/video-add-components/video-import-url.component.scss b/client/src/app/videos/+video-edit/video-add-components/video-import-url.component.scss index 5e713ab97..7c6deda1d 100644 --- a/client/src/app/videos/+video-edit/video-add-components/video-import-url.component.scss +++ b/client/src/app/videos/+video-edit/video-add-components/video-import-url.component.scss @@ -7,7 +7,7 @@ $width-size: 190px; @include peertube-select-container($width-size); } -.import-video { +.import-video-url { display: flex; flex-direction: column; align-items: center; diff --git a/client/src/app/videos/+video-edit/video-add-components/video-import-url.component.ts b/client/src/app/videos/+video-edit/video-add-components/video-import-url.component.ts index dbe69409f..842ede732 100644 --- a/client/src/app/videos/+video-edit/video-add-components/video-import-url.component.ts +++ b/client/src/app/videos/+video-edit/video-add-components/video-import-url.component.ts @@ -74,7 +74,7 @@ export class VideoImportUrlComponent extends VideoSend implements OnInit, CanCom this.loadingBar.start() - this.videoImportService.importVideo(this.targetUrl, videoUpdate).subscribe( + this.videoImportService.importVideoUrl(this.targetUrl, videoUpdate).subscribe( res => { this.loadingBar.complete() this.firstStepDone.emit(res.video.name) diff --git a/client/src/app/videos/+video-edit/video-add.component.html b/client/src/app/videos/+video-edit/video-add.component.html index 7a50372e9..340820180 100644 --- a/client/src/app/videos/+video-edit/video-add.component.html +++ b/client/src/app/videos/+video-edit/video-add.component.html @@ -10,8 +10,12 @@ - + + + + +
diff --git a/client/src/app/videos/+video-edit/video-add.component.ts b/client/src/app/videos/+video-edit/video-add.component.ts index e74fa1f15..7d360598d 100644 --- a/client/src/app/videos/+video-edit/video-add.component.ts +++ b/client/src/app/videos/+video-edit/video-add.component.ts @@ -3,6 +3,7 @@ import { CanComponentDeactivate } from '@app/shared/guards/can-deactivate-guard. import { VideoImportUrlComponent } from '@app/videos/+video-edit/video-add-components/video-import-url.component' import { VideoUploadComponent } from '@app/videos/+video-edit/video-add-components/video-upload.component' import { ServerService } from '@app/core' +import { VideoImportTorrentComponent } from '@app/videos/+video-edit/video-add-components/video-import-torrent.component' @Component({ selector: 'my-videos-add', @@ -12,15 +13,16 @@ import { ServerService } from '@app/core' export class VideoAddComponent implements CanComponentDeactivate { @ViewChild('videoUpload') videoUpload: VideoUploadComponent @ViewChild('videoImportUrl') videoImportUrl: VideoImportUrlComponent + @ViewChild('videoImportTorrent') videoImportTorrent: VideoImportTorrentComponent - secondStepType: 'upload' | 'import-url' + secondStepType: 'upload' | 'import-url' | 'import-torrent' videoName: string constructor ( private serverService: ServerService ) {} - onFirstStepDone (type: 'upload' | 'import-url', videoName: string) { + onFirstStepDone (type: 'upload' | 'import-url' | 'import-torrent', videoName: string) { this.secondStepType = type this.videoName = videoName } @@ -28,11 +30,16 @@ export class VideoAddComponent implements CanComponentDeactivate { canDeactivate () { if (this.secondStepType === 'upload') return this.videoUpload.canDeactivate() if (this.secondStepType === 'import-url') return this.videoImportUrl.canDeactivate() + if (this.secondStepType === 'import-torrent') return this.videoImportTorrent.canDeactivate() return { canDeactivate: true } } - isVideoImportEnabled () { + isVideoImportHttpEnabled () { + return this.serverService.getConfig().import.videos.http.enabled + } + + isVideoImportTorrentEnabled () { return this.serverService.getConfig().import.videos.http.enabled } } diff --git a/client/src/app/videos/+video-edit/video-add.module.ts b/client/src/app/videos/+video-edit/video-add.module.ts index a1324b397..3ecf96459 100644 --- a/client/src/app/videos/+video-edit/video-add.module.ts +++ b/client/src/app/videos/+video-edit/video-add.module.ts @@ -7,6 +7,7 @@ import { VideoAddComponent } from './video-add.component' import { CanDeactivateGuard } from '../../shared/guards/can-deactivate-guard.service' import { VideoUploadComponent } from '@app/videos/+video-edit/video-add-components/video-upload.component' import { VideoImportUrlComponent } from '@app/videos/+video-edit/video-add-components/video-import-url.component' +import { VideoImportTorrentComponent } from '@app/videos/+video-edit/video-add-components/video-import-torrent.component' @NgModule({ imports: [ @@ -18,7 +19,8 @@ import { VideoImportUrlComponent } from '@app/videos/+video-edit/video-add-compo declarations: [ VideoAddComponent, VideoUploadComponent, - VideoImportUrlComponent + VideoImportUrlComponent, + VideoImportTorrentComponent ], exports: [ VideoAddComponent -- cgit v1.2.3