feat(torrents): create music torrents

This commit is contained in:
OldHawk
2017-09-28 18:31:49 +08:00
parent b9df724dfe
commit 38018a507e
10 changed files with 328 additions and 23 deletions

View File

@@ -358,6 +358,15 @@
AGREE_RULES: 'I agree and already read all the rules, <a href="#">read here</a>',
DOWNLOAD_TORRENT: 'Download Torrent',
ENTER_MUSIC_TITLE: '3. Please enter the music/album title',
MUSIC_TITLE: 'title',
MUSIC_SUB_TITLE: 'short desc',
SELECT_MUSIC_IMAGE: '3.1 Please select music/album cover image',
MUSIC_COVER_UPLOAD_SUCCESSFULLY: 'Successfully upload music cover',
MUSIC_COVER_UPLOAD_FAILED: 'Failed to upload music cover',
ENTER_MUSIC_DETAIL_INFO: '4. Please enter the music/album detail info',
ERROR_ONLY_IMAGE: 'Only image files support(gif, png, bmp, jpg, jpeg)',
//ranking view
PAGE_HEADER_RANKING_UPLOAD: 'Uploaded Ranking',
PAGE_HEADER_RANKING_DOWNLOAD: 'Downloaded Ranking',

View File

@@ -358,6 +358,15 @@
AGREE_RULES: '我已阅读并同意站内所有协议条款,<a href="#">协议条款</a>',
DOWNLOAD_TORRENT: '下载种子',
ENTER_MUSIC_TITLE: '3. 请输入音乐/专辑标题',
MUSIC_TITLE: '标题',
MUSIC_SUB_TITLE: '短描述',
SELECT_MUSIC_IMAGE: '3.1 请选择音乐/专辑封面图片',
MUSIC_COVER_UPLOAD_SUCCESSFULLY: '封面图片上传成功',
MUSIC_COVER_UPLOAD_FAILED: '封面图片上传失败',
ENTER_MUSIC_DETAIL_INFO: '4. 请输入音乐/专辑详细信息',
ERROR_ONLY_IMAGE: '此处只支持图片文件上传(gif, png, bmp, jpg, jpeg)',
//ranking view
PAGE_HEADER_RANKING_UPLOAD: '上传量排行榜',
PAGE_HEADER_RANKING_DOWNLOAD: '下载量排行榜',

View File

@@ -4,9 +4,9 @@
angular.module('core')
.directive('mtMarkdownEditor', mtMarkdownEditor);
mtMarkdownEditor.$inject = ['localStorageService', '$compile', 'NotifycationService', '$timeout'];
mtMarkdownEditor.$inject = ['localStorageService', '$compile', 'NotifycationService', '$translate', 'DebugConsoleService', '$timeout'];
function mtMarkdownEditor(localStorageService, $compile, NotifycationService, $timeout) {
function mtMarkdownEditor(localStorageService, $compile, NotifycationService, $translate, mtDebug, $timeout) {
var directive = {
restrict: 'A',
require: 'ngModel',
@@ -32,6 +32,7 @@
scope.uProgress = 0;
scope.uFiles = [];
scope.uImages = [];
scope.$parent.uImages = [];
var eleUploadTip = angular.element('<div class="attach-info" ng-show="!uFile"><div class="attach-upload-tooltip text-long"><span>{{\'FORUMS.ATTACH_UPLOAD_TOOLTIP1\' | translate}}</span><input type="file" class="manual-file-chooser" ng-model="selectedFile" ngf-select="onFileSelected($event);"><span class="btn-link manual-file-chooser-text">{{\'FORUMS.ATTACH_UPLOAD_TOOLTIP2\' | translate}}</span>{{\'FORUMS.ATTACH_UPLOAD_TOOLTIP3\' | translate}}</div></div>');
var eleUploadBegin = angular.element('<div class="upload-info" ng-show="uFile"><i class="fa fa-cog fa-spin fa-lg fa-fw"></i> <div class="attach-upload-progress" style="width: {{uProgress}}%"></div><div class="attach-upload-filename">{{\'FORUMS.ATTACH_UPLOADING\' | translate}}: {{uFile.name}}</div></div>');
@@ -71,10 +72,27 @@
});
function doUpload(sFile) {
if (!sFile) {
return;
}
if (attrs.uploadOnlyImage) {
if (sFile.type !== 'image/png' && sFile.type !== 'image/jpg' && sFile.type !== 'image/jpeg' && sFile.type !== 'image/gif' && sFile.type !== 'image/bmp') {
NotifycationService.showErrorNotify($translate.instant('ERROR_ONLY_IMAGE'), 'ERROR');
console.error($translate.instant('ERROR_ONLY_IMAGE'));
return;
}
}
if (attrs.uploadMethod) {
scope.uFile = sFile;
scope.uProgress = 0;
if (!attrs.uploadDir) {
console.error('uploadMethod must has a uploadDir attr!');
return;
}
scope.$eval(attrs.uploadMethod, {
editor: e,
ufile: scope.uFile,
@@ -89,10 +107,11 @@
var status = '';
var ext = uFile.name.replace(/^.+\./, '').toLowerCase();
if (ext === 'jpg' || ext === 'jpeg' || ext === 'bmp' || ext === 'gif' || ext === 'png') {
status = '\n![' + uFile.name + '](/modules/forums/client/attach/temp/' + uFile.name + ')\n';
status = '\n![' + uFile.name + '](' + attrs.uploadDir + uFile.name + ')\n';
e.replaceSelection(status);
ngModel.$setViewValue($('#' + attrs.mtMarkdownEditor)[0].value);
scope.uImages.push(uFile);
scope.$parent.uImages.push(uFile);
} else {
scope.uFiles.push(uFile);
}

View File

@@ -408,6 +408,7 @@
return false;
}
mtDebug.info($scope.uFiles);
var uf = [];
angular.forEach($scope.uFiles, function (f) {
uf.push({
@@ -416,6 +417,7 @@
});
});
mtDebug.info($scope.uImages);
var uimg = [];
angular.forEach($scope.uImages, function (f) {
uimg.push({

View File

@@ -30,7 +30,9 @@
<div class="form-group" show-errors>
<textarea id="postContent" name="postContent" ng-model="vm.postFields.content"
mt-markdown-editor="postContent" upload-method="vm.uploadAttach(editor, ufile, progressback, callback, errback);" required></textarea>
mt-markdown-editor="postContent"
upload-dir="/modules/forums/client/attach/temp/"
upload-method="vm.uploadAttach(editor, ufile, progressback, callback, errback);" required></textarea>
<div ng-messages="vm.postForm.postContent.$error" role="alert">
<p class="help-block error-text" ng-message="required">{{ 'FORUMS.PC_REQUIRED' | translate}}</p>

View File

@@ -256,6 +256,7 @@
<div class="form-group" show-errors>
<textarea id="postReplyContent" name="postReplyContent" ng-model="vm.postReplyFields.content"
mt-markdown-editor="postReplyContent"
upload-dir="/modules/forums/client/attach/temp/"
upload-method="vm.uploadAttach(editor, ufile, progressback, callback, errback);" required></textarea>
<div ng-messages="vm.replyForm.postReplyContent.$error" role="alert">

View File

@@ -6,10 +6,10 @@
.controller('TorrentsUploadController', TorrentsUploadController);
TorrentsUploadController.$inject = ['$scope', '$state', '$translate', '$timeout', 'Authentication', 'MeanTorrentConfig', 'Upload', 'Notification',
'TorrentsService', 'getStorageLangService', '$filter', 'DownloadService', 'DebugConsoleService'];
'TorrentsService', 'getStorageLangService', '$filter', 'DownloadService', 'DebugConsoleService', 'NotifycationService'];
function TorrentsUploadController($scope, $state, $translate, $timeout, Authentication, MeanTorrentConfig, Upload, Notification,
TorrentsService, getStorageLangService, $filter, DownloadService, mtDebug) {
TorrentsService, getStorageLangService, $filter, DownloadService, mtDebug, NotifycationService) {
var vm = this;
vm.announceConfig = MeanTorrentConfig.meanTorrentConfig.announce;
vm.tmdbConfig = MeanTorrentConfig.meanTorrentConfig.tmdbConfig;
@@ -22,6 +22,7 @@
vm.torrentInfo = null;
vm.tags = [];
vm.videoNfo = '';
vm.music = {};
// If user is not signed in then redirect back home
if (!Authentication.user) {
@@ -90,6 +91,79 @@
});
}
/**
* uploadMusicCover
* @param dataUrl
*/
vm.uploadMusicCover = function (dataUrl) {
mtDebug.info(dataUrl);
if (dataUrl === null || dataUrl === undefined) {
vm.music.fileSelected = false;
Notification.info({
message: '<i class="glyphicon glyphicon-info-sign"></i> ' + $translate.instant('TORRENTS_NO_FILE_SELECTED')
});
return;
}
Upload.upload({
url: '/api/torrents/uploadTorrentCover',
data: {
newTorrentCoverFile: dataUrl
}
}).then(function (response) {
vm.music.fileSelected = false;
vm.music.successfully = true;
mtDebug.info(response);
vm.music.coverFileName = response.data.filename;
Notification.success({
message: '<i class="glyphicon glyphicon-ok"></i> ' + $translate.instant('MUSIC_COVER_UPLOAD_SUCCESSFULLY')
});
}, function (response) {
mtDebug.info(response);
if (response.status > 0) {
vm.music.fileSelected = false;
vm.music.successfully = false;
vm.music.coverFile = undefined;
Notification.error({
message: response.data,
title: '<i class="glyphicon glyphicon-remove"></i> ' + $translate.instant('MUSIC_COVER_UPLOAD_FAILED')
});
}
}, function (evt) {
vm.music.progress = parseInt(100.0 * evt.loaded / evt.total, 10);
});
};
/**
* uploadTorrentImage
* @param editor
* @param ufile
* @param progressback
* @param callback
* @param errback
*/
vm.uploadTorrentImage = function (editor, ufile, progressback, callback, errback) {
Upload.upload({
url: '/api/torrents/uploadTorrentImage',
data: {
newTorrentImageFile: ufile
}
}).then(function (res) {
if (callback) {
callback(res.data.filename);
}
}, function (res) {
if (errback && res.status > 0) {
errback(res);
}
}, function (evt) {
if (progressback) {
progressback(parseInt(100.0 * evt.loaded / evt.total, 10));
}
});
};
/**
* onTMDBIDKeyDown
* @param evt
@@ -347,6 +421,63 @@
}
};
/**
* createMusicTorrent
*/
vm.createMusicTorrent = function () {
var l = vm.getTorrentSize();
var t = vm.getResourceTag();
var detail_info = {
title: vm.music.title,
subtitle: vm.music.subtitle,
cover: vm.music.coverFileName,
detail: vm.music.detail
};
mtDebug.info($scope.uImages);
var uimg = [];
angular.forEach($scope.uImages, function (f) {
mtDebug.info(f);
uimg.push({
filename: f.name
});
});
var torrent = new TorrentsService({
info_hash: vm.torrentInfo.info_hash,
torrent_filename: vm.torrentInfo.filename,
torrent_type: 'music',
torrent_tags: t,
torrent_nfo: vm.videoNfo,
torrent_announce: vm.torrentInfo.announce,
torrent_size: l,
resource_detail_info: detail_info,
_uImage: uimg
});
torrent.$save(function (response) {
successCallback(response);
}, function (errorResponse) {
errorCallback(errorResponse);
});
function successCallback(res) {
vm.downloadTorrent(res._id);
Notification.success({message: '<i class="glyphicon glyphicon-ok"></i> Torrent created successfully!'});
$state.reload('torrents.uploads');
document.body.scrollTop = document.documentElement.scrollTop = 0;
}
function errorCallback(res) {
vm.error_msg = res.data.message;
Notification.error({message: res.data.message, title: '<i class="glyphicon glyphicon-remove"></i> Torrent created error!'});
}
};
/**
* getTorrentSize
* @returns {number}

View File

@@ -24,9 +24,9 @@
var fileName = decodeURI(contentDisposition.substr(contentDisposition.indexOf('filename=') + 9));
FileSaver.saveAs(response.data, fileName);
successcb(response.status);
if (successcb) successcb(response.status);
}, function errorCallback(response) {
errorcb(response);
if (errorcb) errorcb(response);
});
}
}

View File

@@ -46,15 +46,17 @@
<legend class="small-legend" translate="SELECT_RESOURCE_TYPE"></legend>
<div class="col-xs-12 col-sm-6 col-md-4">
<select class="form-control" ng-model="vm.selectedType" ng-change="vm.onTorrentTypeChanged();">
<option ng-repeat="t in vm.torrentType.value | filter:{enable: true}" value="{{t.value}}">{{'MENU_TORRENTS_SUB.'+t.name | translate}}</option>
<option ng-repeat="t in vm.torrentType.value | filter:{enable: true}"
value="{{t.value}}">{{'MENU_TORRENTS_SUB.'+t.name | translate}}
</option>
</select>
</div>
</div>
</div>
<div ng-if="vm.selectedType" ng-include="vm.getIncludeUploadTemplateID(vm.selectedType);"></div>
<div ng-show="vm.selectedType" ng-include="vm.getIncludeUploadTemplateID(vm.selectedType);"></div>
<div class="row margin-bottom-40 margin-top-50" ng-show="vm.showAgreeAndSubmit">
<div class="row margin-bottom-40 margin-top-50" ng-show="vm.showAgreeAndSubmit || vm.music.detail">
<div class="col-md-12 col-sm-12 col-xs-12">
<legend class="small-legend" translate="TORRENTS_SUBMIT_UPLOAD"></legend>
<div class="col-sm-6 col-sm-offset-3 text-center">
@@ -85,7 +87,7 @@
<legend class="small-legend" translate="ENTER_TMDB_ID"></legend>
<div class="col-lg-3 col-md-4 col-sm-5 col-xs-6">
<div class="input-group">
<input type="text" class="form-control" ng-ac ng-model="vm.tmdb_id"
<input type="text" class="form-control" ng-model="vm.tmdb_id"
id="tmdbid"
ng-change="vm.tmdb_info_ok = undefined"
ng-disabled="vm.tmdb_info_ok"
@@ -247,7 +249,7 @@
<legend class="small-legend" translate="ENTER_TMDB_ID"></legend>
<div class="col-lg-3 col-md-4 col-sm-5 col-xs-6">
<div class="input-group">
<input type="text" class="form-control" ng-ac ng-model="vm.tmdb_id"
<input type="text" class="form-control" ng-model="vm.tmdb_id"
id="tmdbid"
ng-change="vm.tmdb_info_ok = undefined"
ng-disabled="vm.tmdb_info_ok"
@@ -443,8 +445,112 @@
ng-template music.html
*********************************************************************** -->
<script type="text/ng-template" id="music">
<div>
<div class="row margin-bottom-40">
<div class="col-md-12 col-sm-12 col-xs-12">
<legend class="small-legend" translate="ENTER_MUSIC_TITLE"></legend>
<div class="col-md-6 col-sm-8">
<input type="text" class="form-control" ng-model="vm.music.title" placeholder="{{ 'MUSIC_TITLE' | translate}}" autofocus>
</div>
<div class="col-md-8 col-sm-10 margin-top-10">
<input type="text" class="form-control" ng-model="vm.music.subtitle" placeholder="{{ 'MUSIC_SUB_TITLE' | translate}}">
</div>
</div>
</div>
<div class="row margin-bottom-40" ng-show="vm.music.title && vm.music.subtitle">
<div class="col-xs-12">
<legend class="small-legend" translate="SELECT_MUSIC_IMAGE"></legend>
<div class="col-sm-7">
<div class="input-group">
<input type="text" class="form-control" ng-model="vm.music.coverFile.name" disabled>
<div class="input-group-btn">
<button class="btn btn-primary btn-file"
ngf-select="vm.music.fileSelected = true; vm.music.successfully = undefined; vm.music.progress = 0;"
ng-model="vm.music.coverFile"
ngf-pattern="'image/*'"
ngf-accept="'image/*'"
ngf-resize="{width: 400}"
ngf-resize-if="$width > 400 || $height > 400"
ng-disabled="vm.music.successfully">{{ 'SELECT_FILE' | translate}}
</button>
</div>
</div>
</div>
<div ng-show="vm.music.fileSelected" class="col-sm-5">
<button class="btn btn-success"
ng-click="vm.uploadMusicCover(vm.music.coverFile)">{{ 'DO_UPLOAD' | translate}} ({{vm.music.progress}}%)
</button>
</div>
<div ng-show="vm.music.successfully == true" class="col-sm-5" style="margin-top: 7px">
<label class="text-success control-label" translate="MUSIC_COVER_UPLOAD_SUCCESSFULLY"></label>
</div>
<div ng-show="vm.music.successfully == false" class="col-sm-5" style="margin-top: 7px">
<label class="text-danger control-label" translate="MUSIC_COVER_UPLOAD_FAILED"></label>
</div>
</div>
</div>
<div class="row margin-bottom-40" ng-show="vm.music.successfully">
<div class="col-md-12 col-sm-12 col-xs-12">
<legend class="small-legend" translate="ENTER_MUSIC_DETAIL_INFO"></legend>
<div class="col-xs-12">
<textarea id="musicDetail" name="musicDetail" ng-model="vm.music.detail"
mt-markdown-editor="musicDetail"
upload-dir="/modules/torrents/client/uploads/temp/"
upload-only-image="true"
upload-method="vm.uploadTorrentImage(editor, ufile, progressback, callback, errback);"></textarea>
</div>
</div>
</div>
<div class="row margin-bottom-40" ng-show="vm.music.detail">
<div class="col-md-12 col-sm-12 col-xs-12">
<legend class="small-legend" translate="SELECT_TAGS"></legend>
<dl class="dl-horizontal">
<div ng-repeat="item in vm.resourcesTags.radio | filter:vm.selectedType">
<dt class="h-line">{{ 'RESOURCESTAGS.'+item.name+'.SELF' | translate}}</dt>
<dd class="h-line">
<label class="radio-inline" ng-repeat="sitem in item.value">
<input type="radio" class="tradio" name="tag_{{item.name}}" ng-model="vm.tags['tag_'+item.name]"
id="radio_{{item.name}}{{$index}}"
value="{{sitem.name}}"> {{ 'RESOURCESTAGS.' + item.name + '.' + sitem.name | translate}}
</label>
</dd>
</div>
<div style="margin-top: 30px;"></div>
<div ng-repeat="item in vm.resourcesTags.checkbox | filter:vm.selectedType">
<dt class="h-line">{{ 'RESOURCESTAGS.'+item.name+'.SELF' | translate}}</dt>
<dd class="h-line">
<label class="checkbox-inline" ng-repeat="sitem in item.value">
<input type="checkbox" class="tcheckbox" ng-model="vm.tags['tag_'+item.name+'_'+sitem.name]"
id="checkbox_{{item.name}}_{{sitem.name}}"
value="{{sitem.name}}"> {{ 'RESOURCESTAGS.' + item.name + '.' + sitem.name | translate}}
</label>
</dd>
</div>
<div class="margin-top-10">
<dt class="h-line"></dt>
<dd class="h-line">
<span class="label label-tag text-uppercase" ng-click="vm.clearAllCondition();">
{{ 'CLEAR_ALL_CONDITION' | translate}}
</span>
</dd>
</div>
</dl>
</div>
</div>
<div class="row margin-bottom-40" ng-show="vm.music.detail">
<div class="col-md-12 col-sm-12 col-xs-12">
<legend class="small-legend" translate="ENTER_VIDEO_NFO"></legend>
<div class="col-xs-12">
<textarea class="form-control" rows="10" ng-model="vm.music.videoNfo" style="resize: vertical"></textarea>
</div>
</div>
</div>
</script>
<!-- **********************************************************************

View File

@@ -157,14 +157,14 @@ exports.upload = function (req, res) {
message = 'Read torrent file faild';
reject(message);
} else {
if (config.meanTorrentConfig.announce.privateTorrentCmsMode) {
if (torrent.metadata.announce !== config.meanTorrentConfig.announce.url) {
mtDebug.debugGreen(torrent.metadata.announce);
message = 'ANNOUNCE_URL_ERROR';
reject(message);
}
}
//if (config.meanTorrentConfig.announce.privateTorrentCmsMode) {
// if (torrent.metadata.announce !== config.meanTorrentConfig.announce.url) {
// mtDebug.debugGreen(torrent.metadata.announce);
// message = 'ANNOUNCE_URL_ERROR';
//
// reject(message);
// }
//}
torrentinfo = torrent.metadata;
torrentinfo.info_hash = torrent.infoHash();
torrentinfo.filename = req.file.filename;
@@ -501,9 +501,15 @@ exports.download = function (req, res) {
*/
exports.create = function (req, res) {
var torrent = new Torrent(req.body);
mtDebug.debugGreen(req.body);
torrent.user = req.user;
//mtDebug.debugGreen(torrent);
//replace content path
var regex = new RegExp(config.uploads.torrent.image.temp, 'g');
torrent.resource_detail_info.detail = torrent.resource_detail_info.detail.replace(regex, config.uploads.torrent.image.dest);
mtDebug.debugGreen(torrent);
//move temp torrent file to dest directory
var oldPath = config.uploads.torrent.file.temp + req.body.torrent_filename;
@@ -514,6 +520,26 @@ exports.create = function (req, res) {
message: 'MOVE_TORRENT_FILE_ERROR'
});
} else {
//move temp cover image file to dest directory
var cv = req.body.resource_detail_info.cover;
var o = config.uploads.torrent.cover.temp + cv;
var n = config.uploads.torrent.cover.dest + cv;
move(o, n, function (err) {
if (err) {
mtDebug.debugRed(err);
}
});
//move temp torrent image file to dest directory
req.body._uImage.forEach(function (f) {
o = config.uploads.torrent.image.temp + f.filename;
n = config.uploads.torrent.image.dest + f.filename;
move(o, n, function (err) {
if (err) {
mtDebug.debugRed(err);
}
});
});
torrent.save(function (err) {
if (err) {
return res.status(422).send({