From 0f6193b4500692c906ca3d4cf93b54f15eadb672 Mon Sep 17 00:00:00 2001 From: bill bittner Date: Wed, 25 Jul 2018 14:25:40 -0700 Subject: [PATCH 01/14] added migration for db --- .../File_AddHeightAndWidthColumn.js | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 server/migrations/File_AddHeightAndWidthColumn.js diff --git a/server/migrations/File_AddHeightAndWidthColumn.js b/server/migrations/File_AddHeightAndWidthColumn.js new file mode 100644 index 00000000..03aad049 --- /dev/null +++ b/server/migrations/File_AddHeightAndWidthColumn.js @@ -0,0 +1,34 @@ +module.exports = { + up: (queryInterface, Sequelize) => { + // logic for transforming into the new state + const changeOne = queryInterface.addColumn( + 'File', + 'height', + { + type : Sequelize.INTEGER, + allowNull: false, + } + ); + const changeTwo = queryInterface.addColumn( + 'File', + 'width', + { + type : Sequelize.INTEGER, + allowNull: false, + } + ); + return Promise.all([changeOne, changeTwo]); + }, + down: (queryInterface, Sequelize) => { + // logic for reverting the changes + const reversionOne = queryInterface.removeColumn( + 'File', + 'height' + ); + const reversionTwo = queryInterface.removeColumn( + 'File', + 'width', + ); + return Promise.all([reversionOne, reversionTwo]); + }, +}; -- 2.45.3 From 2d7dbdc8a0d3d6661911aca019eb482c428a38d5 Mon Sep 17 00:00:00 2001 From: bill bittner Date: Wed, 25 Jul 2018 17:21:02 -0700 Subject: [PATCH 02/14] added a migration for File table --- .../api/claim/get/addGetResultsToFileData.js | 4 +- .../api/claim/get/createFileData.js | 4 +- server/controllers/api/claim/get/index.js | 30 +++-- .../File_AddHeightAndWidthColumn.js | 112 +++++++++++++----- server/models/file.js | 29 +---- 5 files changed, 116 insertions(+), 63 deletions(-) diff --git a/server/controllers/api/claim/get/addGetResultsToFileData.js b/server/controllers/api/claim/get/addGetResultsToFileData.js index 3fe3cc43..b07c556d 100644 --- a/server/controllers/api/claim/get/addGetResultsToFileData.js +++ b/server/controllers/api/claim/get/addGetResultsToFileData.js @@ -1,5 +1,7 @@ -module.exports = (fileInfo, getResult) => { +const addGetResultsToFileData = (fileInfo, getResult) => { fileInfo.fileName = getResult.file_name; fileInfo.filePath = getResult.download_path; return fileInfo; }; + +module.exports = addGetResultsToFileData; diff --git a/server/controllers/api/claim/get/createFileData.js b/server/controllers/api/claim/get/createFileData.js index 71d295ab..d7f69137 100644 --- a/server/controllers/api/claim/get/createFileData.js +++ b/server/controllers/api/claim/get/createFileData.js @@ -1,4 +1,4 @@ -module.exports = ({ name, claimId, outpoint, height, address, nsfw, contentType }) => { +const createFileData = ({ name, claimId, outpoint, height, address, nsfw, contentType }) => { return { name, claimId, @@ -11,3 +11,5 @@ module.exports = ({ name, claimId, outpoint, height, address, nsfw, contentType nsfw, }; }; + +module.exports = createFileData; diff --git a/server/controllers/api/claim/get/index.js b/server/controllers/api/claim/get/index.js index 1a8757e8..f0a76d71 100644 --- a/server/controllers/api/claim/get/index.js +++ b/server/controllers/api/claim/get/index.js @@ -13,23 +13,35 @@ const db = require('../../../../models'); const claimGet = ({ ip, originalUrl, params }, res) => { const name = params.name; const claimId = params.claimId; + let fileData; + let resolveResult; + let getResult; + let message; + let completed; // resolve the claim db.Claim.resolveClaim(name, claimId) - .then(resolveResult => { + .then(result => { // make sure a claim actually exists at that uri - if (!resolveResult) { + if (!result) { throw new Error('No matching uri found in Claim table'); } - let fileData = createFileData(resolveResult); - // get the claim - return Promise.all([fileData, getClaim(`${name}#${claimId}`)]); + resolveResult = result; + return getClaim(`${name}#${claimId}`); }) - .then(([ fileData, getResult ]) => { + .then(result => { + getResult = result; + fileData = createFileData(resolveResult); fileData = addGetResultsToFileData(fileData, getResult); - return Promise.all([db.upsert(db.File, fileData, {name, claimId}, 'File'), getResult]); + const upsertCriteria = { name, claimId}; + return db.upsert(db.File, fileData, upsertCriteria, 'File'); }) - .then(([ fileRecord, {message, completed} ]) => { - res.status(200).json({ success: true, message, completed }); + .then(() => { + ({ message, completed } = getResult); + res.status(200).json({ + success: true, + message, + completed, + }); }) .catch(error => { handleErrorResponse(originalUrl, ip, error, res); diff --git a/server/migrations/File_AddHeightAndWidthColumn.js b/server/migrations/File_AddHeightAndWidthColumn.js index 03aad049..c6ccc5be 100644 --- a/server/migrations/File_AddHeightAndWidthColumn.js +++ b/server/migrations/File_AddHeightAndWidthColumn.js @@ -1,34 +1,88 @@ module.exports = { - up: (queryInterface, Sequelize) => { + up: (queryInterface, { INTEGER }) => { // logic for transforming into the new state - const changeOne = queryInterface.addColumn( - 'File', - 'height', - { - type : Sequelize.INTEGER, - allowNull: false, - } - ); - const changeTwo = queryInterface.addColumn( - 'File', - 'width', - { - type : Sequelize.INTEGER, - allowNull: false, - } - ); - return Promise.all([changeOne, changeTwo]); + return Promise.all([ + queryInterface.addColumn( + 'File', + 'fileHeight', + { + type : INTEGER, + allowNull: false, + default : 0, + } + ), + queryInterface.addColumn( + 'File', + 'fileWidth', + { + type : INTEGER, + allowNull: false, + default : 0, + } + ), + queryInterface.removeColumn( + 'File', + 'address', + ), + queryInterface.removeColumn( + 'File', + 'height', + ), + queryInterface.removeColumn( + 'File', + 'nsfw', + ), + queryInterface.removeColumn( + 'File', + 'trendingEligible', + ), + ]); }, - down: (queryInterface, Sequelize) => { - // logic for reverting the changes - const reversionOne = queryInterface.removeColumn( - 'File', - 'height' - ); - const reversionTwo = queryInterface.removeColumn( - 'File', - 'width', - ); - return Promise.all([reversionOne, reversionTwo]); + down: (queryInterface, { BOOLEAN, INTEGER, STRING }) => { + return Promise.all([ + queryInterface.removeColumn( + 'File', + 'fileHeight', + ), + queryInterface.removeColumn( + 'File', + 'fileWidth', + ), + queryInterface.addColumn( + 'File', + 'address', + { + type : STRING, + allowNull: false, + } + ), + queryInterface.addColumn( + 'File', + 'height', + { + type : INTEGER, + allowNull: false, + default : 0, + } + ), + queryInterface.addColumn( + 'File', + 'nsfw', + { + type : BOOLEAN, + allowNull : false, + defaultValue: false, + } + ), + queryInterface.addColumn( + 'File', + 'trendingEligible', + { + type : BOOLEAN, + allowNull : false, + defaultValue: true, + } + ), + ]); }, }; diff --git a/server/models/file.js b/server/models/file.js index 1ba0b5fa..cbce718c 100644 --- a/server/models/file.js +++ b/server/models/file.js @@ -10,15 +10,16 @@ module.exports = (sequelize, { STRING, BOOLEAN, INTEGER }) => { type : STRING, allowNull: false, }, - address: { - type : STRING, - allowNull: false, - }, outpoint: { type : STRING, allowNull: false, }, - height: { + fileHeight: { + type : INTEGER, + allowNull: false, + default : 0, + }, + fileWidth: { type : INTEGER, allowNull: false, default : 0, @@ -34,16 +35,6 @@ module.exports = (sequelize, { STRING, BOOLEAN, INTEGER }) => { fileType: { type: STRING, }, - nsfw: { - type : BOOLEAN, - allowNull : false, - defaultValue: false, - }, - trendingEligible: { - type : BOOLEAN, - allowNull : false, - defaultValue: true, - }, }, { freezeTableName: true, @@ -55,13 +46,5 @@ module.exports = (sequelize, { STRING, BOOLEAN, INTEGER }) => { File.hasOne(db.Claim); }; - File.getRecentClaims = function () { - return this.findAll({ - where: { nsfw: false, trendingEligible: true }, - order: [['createdAt', 'DESC']], - limit: 25, - }); - }; - return File; }; -- 2.45.3 From 82f56ccc9a8ca25f459af374ba178e426c53f109 Mon Sep 17 00:00:00 2001 From: bill bittner Date: Wed, 25 Jul 2018 17:29:59 -0700 Subject: [PATCH 03/14] simplified File data creation --- .../api/claim/get/addGetResultsToFileData.js | 7 ------- .../controllers/api/claim/get/createFileData.js | 11 ++++------- server/controllers/api/claim/get/index.js | 16 ++++++---------- 3 files changed, 10 insertions(+), 24 deletions(-) delete mode 100644 server/controllers/api/claim/get/addGetResultsToFileData.js diff --git a/server/controllers/api/claim/get/addGetResultsToFileData.js b/server/controllers/api/claim/get/addGetResultsToFileData.js deleted file mode 100644 index b07c556d..00000000 --- a/server/controllers/api/claim/get/addGetResultsToFileData.js +++ /dev/null @@ -1,7 +0,0 @@ -const addGetResultsToFileData = (fileInfo, getResult) => { - fileInfo.fileName = getResult.file_name; - fileInfo.filePath = getResult.download_path; - return fileInfo; -}; - -module.exports = addGetResultsToFileData; diff --git a/server/controllers/api/claim/get/createFileData.js b/server/controllers/api/claim/get/createFileData.js index d7f69137..00594ea5 100644 --- a/server/controllers/api/claim/get/createFileData.js +++ b/server/controllers/api/claim/get/createFileData.js @@ -1,14 +1,11 @@ -const createFileData = ({ name, claimId, outpoint, height, address, nsfw, contentType }) => { +const createFileData = ({ name, claimId, outpoint, contentType: fileType }, { file_name: fileName, download_path: filePath }) => { return { name, claimId, outpoint, - height, - address, - fileName: '', - filePath: '', - fileType: contentType, - nsfw, + fileName, + filePath, + fileType, }; }; diff --git a/server/controllers/api/claim/get/index.js b/server/controllers/api/claim/get/index.js index f0a76d71..0d33b7a3 100644 --- a/server/controllers/api/claim/get/index.js +++ b/server/controllers/api/claim/get/index.js @@ -1,5 +1,4 @@ const { getClaim } = require('../../../../lbrynet'); -const addGetResultsToFileData = require('./addGetResultsToFileData.js'); const createFileData = require('./createFileData.js'); const { handleErrorResponse } = require('../../../utils/errorHandlers.js'); const db = require('../../../../models'); @@ -13,15 +12,11 @@ const db = require('../../../../models'); const claimGet = ({ ip, originalUrl, params }, res) => { const name = params.name; const claimId = params.claimId; - let fileData; let resolveResult; let getResult; - let message; - let completed; // resolve the claim db.Claim.resolveClaim(name, claimId) .then(result => { - // make sure a claim actually exists at that uri if (!result) { throw new Error('No matching uri found in Claim table'); } @@ -30,13 +25,14 @@ const claimGet = ({ ip, originalUrl, params }, res) => { }) .then(result => { getResult = result; - fileData = createFileData(resolveResult); - fileData = addGetResultsToFileData(fileData, getResult); - const upsertCriteria = { name, claimId}; - return db.upsert(db.File, fileData, upsertCriteria, 'File'); }) .then(() => { - ({ message, completed } = getResult); + const fileData = createFileData(resolveResult, getResult); + const upsertCriteria = { name, claimId}; + return db.upsert(db.File, fileData, upsertCriteria, 'File') + }) + .then(() => { + const { message, completed } = getResult; res.status(200).json({ success: true, message, -- 2.45.3 From 0b52a819c0ea8c1ffd483d70ceed13308d239933 Mon Sep 17 00:00:00 2001 From: bill bittner Date: Thu, 26 Jul 2018 10:23:31 -0700 Subject: [PATCH 04/14] removed Request table --- server/models/index.js | 2 -- server/models/request.js | 37 ------------------------------------- 2 files changed, 39 deletions(-) delete mode 100644 server/models/request.js diff --git a/server/models/index.js b/server/models/index.js index a13d58ec..f15a453c 100644 --- a/server/models/index.js +++ b/server/models/index.js @@ -5,7 +5,6 @@ const Certificate = require('./certificate.js'); const Channel = require('./channel.js'); const Claim = require('./claim.js'); const File = require('./file.js'); -const Request = require('./request.js'); const User = require('./user.js'); const Blocked = require('./blocked.js'); const Tor = require('./tor.js'); @@ -48,7 +47,6 @@ db['Certificate'] = sequelize.import('Certificate', Certificate); db['Channel'] = sequelize.import('Channel', Channel); db['Claim'] = sequelize.import('Claim', Claim); db['File'] = sequelize.import('File', File); -db['Request'] = sequelize.import('Request', Request); db['User'] = sequelize.import('User', User); db['Blocked'] = sequelize.import('Blocked', Blocked); db['Tor'] = sequelize.import('Tor', Tor); diff --git a/server/models/request.js b/server/models/request.js deleted file mode 100644 index 501fb441..00000000 --- a/server/models/request.js +++ /dev/null @@ -1,37 +0,0 @@ -module.exports = (sequelize, { STRING, BOOLEAN, TEXT }) => { - const Request = sequelize.define( - 'Request', - { - action: { - type : STRING, - allowNull: false, - }, - url: { - type : STRING, - allowNull: false, - }, - ipAddress: { - type : STRING, - allowNull: true, - }, - result: { - type : TEXT('long'), - allowNull: true, - default : null, - }, - }, - { - freezeTableName: true, - } - ); - - Request.associate = db => { - Request.belongsTo(db.File, { - foreignKey: { - allowNull: true, - }, - }); - }; - - return Request; -}; -- 2.45.3 From 62137f3ca938f460e38b448361a01c8b08fca373 Mon Sep 17 00:00:00 2001 From: bill bittner Date: Thu, 26 Jul 2018 13:48:53 -0700 Subject: [PATCH 05/14] refactored File and Claim data creating functions --- package-lock.json | 5 ++ package.json | 1 + .../api/claim/get/createFileData.js | 12 ---- server/controllers/api/claim/get/index.js | 4 +- .../controllers/api/claim/publish/publish.js | 53 +++++---------- server/models/file.js | 1 - server/models/utils/createClaimRecordData.js | 37 +++++++++++ server/models/utils/createFileRecordData.js | 66 +++++++++++++++++++ 8 files changed, 129 insertions(+), 50 deletions(-) delete mode 100644 server/controllers/api/claim/get/createFileData.js create mode 100644 server/models/utils/createClaimRecordData.js create mode 100644 server/models/utils/createFileRecordData.js diff --git a/package-lock.json b/package-lock.json index 2e9a4fd1..049bbc8e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4377,6 +4377,11 @@ "integrity": "sha1-SMptcvbGo68Aqa1K5odr44ieKwk=", "dev": true }, + "image-size": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.6.3.tgz", + "integrity": "sha512-47xSUiQioGaB96nqtp5/q55m0aBQSQdyIloMOc/x+QVTDZLNmXE892IIDrJ0hM1A5vcNUDD5tDffkSP5lCaIIA==" + }, "import-lazy": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", diff --git a/package.json b/package.json index 065928fb..07b22ca4 100644 --- a/package.json +++ b/package.json @@ -38,6 +38,7 @@ "express": "^4.15.2", "express-handlebars": "^3.0.0", "helmet": "^3.8.1", + "image-size": "^0.6.3", "module-alias": "^2.0.6", "mysql2": "^1.3.5", "passport": "^0.4.0", diff --git a/server/controllers/api/claim/get/createFileData.js b/server/controllers/api/claim/get/createFileData.js deleted file mode 100644 index 00594ea5..00000000 --- a/server/controllers/api/claim/get/createFileData.js +++ /dev/null @@ -1,12 +0,0 @@ -const createFileData = ({ name, claimId, outpoint, contentType: fileType }, { file_name: fileName, download_path: filePath }) => { - return { - name, - claimId, - outpoint, - fileName, - filePath, - fileType, - }; -}; - -module.exports = createFileData; diff --git a/server/controllers/api/claim/get/index.js b/server/controllers/api/claim/get/index.js index 0d33b7a3..8ab81844 100644 --- a/server/controllers/api/claim/get/index.js +++ b/server/controllers/api/claim/get/index.js @@ -1,5 +1,5 @@ const { getClaim } = require('../../../../lbrynet'); -const createFileData = require('./createFileData.js'); +const { createFileRecordDataAfterGet } = require('../../../../models/utils/createFileRecordData.js'); const { handleErrorResponse } = require('../../../utils/errorHandlers.js'); const db = require('../../../../models'); @@ -27,7 +27,7 @@ const claimGet = ({ ip, originalUrl, params }, res) => { getResult = result; }) .then(() => { - const fileData = createFileData(resolveResult, getResult); + const fileData = createFileRecordDataAfterGet(resolveResult, getResult); const upsertCriteria = { name, claimId}; return db.upsert(db.File, fileData, upsertCriteria, 'File') }) diff --git a/server/controllers/api/claim/publish/publish.js b/server/controllers/api/claim/publish/publish.js index b80dc0b7..425c3b50 100644 --- a/server/controllers/api/claim/publish/publish.js +++ b/server/controllers/api/claim/publish/publish.js @@ -1,6 +1,8 @@ const logger = require('winston'); -const db = require('../../../../models'); const { publishClaim } = require('../../../../lbrynet'); +const db = require('../../../../models'); +const { createFileRecordDataAfterPublish } = require('../../../../models/utils/createFileRecordData.js'); +const { createClaimRecordDataAfterPublish } = require('../../../../models/utils/createClaimRecordData.js'); const deleteFile = require('./deleteFile.js'); const publish = (publishParams, fileName, fileType) => { @@ -35,51 +37,32 @@ const publish = (publishParams, fileName, fileType) => { logger.debug(`certificateId: ${certificateId}`); }) .then(() => { + const { name, claim_id: claimId } = publishParams; // create the File record - const fileRecord = { - name : publishParams.name, - claimId : publishResults.claim_id, - title : publishParams.metadata.title, - description: publishParams.metadata.description, - address : publishParams.claim_address, - outpoint : `${publishResults.txid}:${publishResults.nout}`, - height : 0, - fileName, - filePath : publishParams.file_path, - fileType, - nsfw : publishParams.metadata.nsfw, - }; + const fileRecord = createFileRecordDataAfterPublish(fileName, fileType, publishParams, publishResults); // create the Claim record - const claimRecord = { - name : publishParams.name, - claimId : publishResults.claim_id, - title : publishParams.metadata.title, - description: publishParams.metadata.description, - address : publishParams.claim_address, - thumbnail : publishParams.metadata.thumbnail, - outpoint : `${publishResults.txid}:${publishResults.nout}`, - height : 0, - contentType: fileType, - nsfw : publishParams.metadata.nsfw, - amount : publishParams.bid, - certificateId, - channelName, - }; - // upsert criteria + const claimRecord = createClaimRecordDataAfterPublish(certificateId, channelName, fileName, fileType, publishParams, publishResults); const upsertCriteria = { - name : publishParams.name, - claimId: publishResults.claim_id, + name, + claimId, }; // upsert the records - return Promise.all([db.upsert(db.File, fileRecord, upsertCriteria, 'File'), db.upsert(db.Claim, claimRecord, upsertCriteria, 'Claim')]); + return Promise.all([ + db.upsert(db.File, fileRecord, upsertCriteria, 'File'), + db.upsert(db.Claim, claimRecord, upsertCriteria, 'Claim'), + ]); }) .then(([file, claim]) => { logger.debug('File and Claim records successfully created'); - return Promise.all([file.setClaim(claim), claim.setFile(file)]); + return Promise.all([ + file.setClaim(claim), + claim.setFile(file), + ]); }) .then(() => { logger.debug('File and Claim records successfully associated'); - resolve(publishResults); // resolve the promise with the result from lbryApi publishClaim; + // resolve the promise with the result from lbryApi publishClaim; + resolve(publishResults); }) .catch(error => { logger.error('PUBLISH ERROR', error); diff --git a/server/models/file.js b/server/models/file.js index cbce718c..0566384d 100644 --- a/server/models/file.js +++ b/server/models/file.js @@ -42,7 +42,6 @@ module.exports = (sequelize, { STRING, BOOLEAN, INTEGER }) => { ); File.associate = db => { - File.hasMany(db.Request); File.hasOne(db.Claim); }; diff --git a/server/models/utils/createClaimRecordData.js b/server/models/utils/createClaimRecordData.js new file mode 100644 index 00000000..ba42abd7 --- /dev/null +++ b/server/models/utils/createClaimRecordData.js @@ -0,0 +1,37 @@ +const createClaimRecordDataAfterPublish = (certificateId, channelName, fileType, publishParams, publishResults) => { + const { + name, + metadata: { + title, + description, + thumbnail, + nsfw, + }, + claim_address: address, + bid: amount, + } = publishParams; + const { + claim_id: claimId, + txid, + nout, + } = publishResults; + return { + name, + claimId, + title, + description, + address, + thumbnail, + outpoint : `${txid}:${nout}`, + height : 0, + contentType: fileType, + nsfw, + amount, + certificateId, + channelName, + }; +}; + +module.exports = { + createClaimRecordDataAfterPublish, +}; diff --git a/server/models/utils/createFileRecordData.js b/server/models/utils/createFileRecordData.js new file mode 100644 index 00000000..7806fcd2 --- /dev/null +++ b/server/models/utils/createFileRecordData.js @@ -0,0 +1,66 @@ +const logger = require('winston'); +const sizeOf = require('image-size'); + +const getFileDimensions = (fileType, filePath) => { + let height = 0; + let width = 0; + switch (fileType) { + case 'image/jpeg': + case 'image/jpg': + case 'image/png': + case 'image/gif': + logger.debug('creating File data for an image'); + const dimensions = sizeOf(filePath); + height = dimensions.height; + width = dimensions.width; + break; + case 'video/mp4': + logger.debug('creating File data for a video'); + break; + default: + logger.error('unable to create File data for unspported file type:', fileType); + break; + } + return { + height, + width, + }; +}; + +const createFileRecordDataAfterGet = (resolveResult, getResult) => { + const { name, claimId, outpoint, contentType: fileType } = resolveResult; + const { file_name: fileName, download_path: filePath } = getResult; + const { height: fileHeight, width: fileWidth } = getFileDimensions(fileType, filePath); + return { + name, + claimId, + outpoint, + fileHeight, + fileWidth, + fileName, + filePath, + fileType, + }; +}; + +const createFileRecordDataAfterPublish = (fileName, fileType, publishParams, publishResults) => { + const { name, claim_id: claimId, file_path: filePath } = publishParams; + const { txid, nout } = publishResults; + const { height: fileHeight, width: fileWidth } = getFileDimensions(fileType, filePath); + + return { + name, + claimId, + outpoint: `${txid}:${nout}`, + fileHeight, + fileWidth, + fileName, + filePath, + fileType, + }; +}; + +module.exports = { + createFileRecordDataAfterGet, + createFileRecordDataAfterPublish, +}; -- 2.45.3 From 3db9e8e4cab655c1c0097c09bdf566f35974d66b Mon Sep 17 00:00:00 2001 From: bill bittner Date: Thu, 26 Jul 2018 15:32:33 -0700 Subject: [PATCH 06/14] updated sequelize cli paths via .sequelizerc --- .sequelizerc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.sequelizerc b/.sequelizerc index 757fef10..fe827ed6 100644 --- a/.sequelizerc +++ b/.sequelizerc @@ -2,4 +2,7 @@ const path = require('path'); module.exports = { 'config': path.resolve('devConfig', 'sequelizeCliConfig.js'), + 'models-path': path.resolve('server', 'models'), + 'seeders-path': path.resolve('server', 'seeders'), + 'migrations-path': path.resolve('server', 'migrations') } -- 2.45.3 From 59cb5b24ee90aada34b41959bf3379eef84ce693 Mon Sep 17 00:00:00 2001 From: bill bittner Date: Thu, 26 Jul 2018 17:57:26 -0700 Subject: [PATCH 07/14] updated code formatting --- server/models/utils/createClaimRecordData.js | 4 ++- server/models/utils/createFileRecordData.js | 33 +++++++++++++++++--- 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/server/models/utils/createClaimRecordData.js b/server/models/utils/createClaimRecordData.js index ba42abd7..91e25ca3 100644 --- a/server/models/utils/createClaimRecordData.js +++ b/server/models/utils/createClaimRecordData.js @@ -1,4 +1,4 @@ -const createClaimRecordDataAfterPublish = (certificateId, channelName, fileType, publishParams, publishResults) => { +const createClaimRecordDataAfterPublish = (certificateId, channelName, fileName, fileType, publishParams, publishResults) => { const { name, metadata: { @@ -10,11 +10,13 @@ const createClaimRecordDataAfterPublish = (certificateId, channelName, fileType, claim_address: address, bid: amount, } = publishParams; + const { claim_id: claimId, txid, nout, } = publishResults; + return { name, claimId, diff --git a/server/models/utils/createFileRecordData.js b/server/models/utils/createFileRecordData.js index 7806fcd2..60ed87d4 100644 --- a/server/models/utils/createFileRecordData.js +++ b/server/models/utils/createFileRecordData.js @@ -28,9 +28,23 @@ const getFileDimensions = (fileType, filePath) => { }; const createFileRecordDataAfterGet = (resolveResult, getResult) => { - const { name, claimId, outpoint, contentType: fileType } = resolveResult; - const { file_name: fileName, download_path: filePath } = getResult; - const { height: fileHeight, width: fileWidth } = getFileDimensions(fileType, filePath); + const { + name, + claimId, + outpoint, + contentType: fileType, + } = resolveResult; + + const { + file_name: fileName, + download_path: filePath, + } = getResult; + + const { + height: fileHeight, + width: fileWidth, + } = getFileDimensions(fileType, filePath); + return { name, claimId, @@ -44,8 +58,17 @@ const createFileRecordDataAfterGet = (resolveResult, getResult) => { }; const createFileRecordDataAfterPublish = (fileName, fileType, publishParams, publishResults) => { - const { name, claim_id: claimId, file_path: filePath } = publishParams; - const { txid, nout } = publishResults; + const { + name, + file_path: filePath, + } = publishParams; + + const { + claim_id: claimId, + txid, + nout, + } = publishResults; + const { height: fileHeight, width: fileWidth } = getFileDimensions(fileType, filePath); return { -- 2.45.3 From 6da08a5f47e4d90c57529996b16dccfd56edb669 Mon Sep 17 00:00:00 2001 From: bill bittner Date: Thu, 26 Jul 2018 18:08:50 -0700 Subject: [PATCH 08/14] added get-video-dimension to package.json --- package-lock.json | 44 ++++++++++++++++++++++++++++++++++++++++++++ package.json | 1 + 2 files changed, 45 insertions(+) diff --git a/package-lock.json b/package-lock.json index 049bbc8e..543859b4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -953,6 +953,11 @@ "resolved": "https://registry.npmjs.org/ansicolors/-/ansicolors-0.2.1.tgz", "integrity": "sha1-vgiVmQl7dKXJxKhKDNvNtivYeu8=" }, + "any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=" + }, "anymatch": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", @@ -3984,6 +3989,14 @@ "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", "dev": true }, + "get-video-dimensions": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-video-dimensions/-/get-video-dimensions-1.0.0.tgz", + "integrity": "sha1-/H5ayBw5JEH1uG1Q3XeDiptTFHo=", + "requires": { + "mz": "1.3.0" + } + }, "getpass": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", @@ -5376,6 +5389,16 @@ } } }, + "mz": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-1.3.0.tgz", + "integrity": "sha1-BvCT/dmVagbTfhsegTROJ0eMQvA=", + "requires": { + "native-or-bluebird": "1.2.0", + "thenify": "3.3.0", + "thenify-all": "1.6.0" + } + }, "named-placeholders": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.1.tgz", @@ -5436,6 +5459,11 @@ } } }, + "native-or-bluebird": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/native-or-bluebird/-/native-or-bluebird-1.2.0.tgz", + "integrity": "sha1-OcR7/Xgl0fuf+tMiEK4l2q3xAck=" + }, "natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -7750,6 +7778,22 @@ "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", "dev": true }, + "thenify": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.0.tgz", + "integrity": "sha1-5p44obq+lpsBCCB5eLn2K4hgSDk=", + "requires": { + "any-promise": "1.3.0" + } + }, + "thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha1-GhkY1ALY/D+Y+/I02wvMjMEOlyY=", + "requires": { + "thenify": "3.3.0" + } + }, "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", diff --git a/package.json b/package.json index 07b22ca4..85da362c 100644 --- a/package.json +++ b/package.json @@ -37,6 +37,7 @@ "cookie-session": "^2.0.0-beta.3", "express": "^4.15.2", "express-handlebars": "^3.0.0", + "get-video-dimensions": "^1.0.0", "helmet": "^3.8.1", "image-size": "^0.6.3", "module-alias": "^2.0.6", -- 2.45.3 From aa1784417e0a0460ccb0156998194977ed721989 Mon Sep 17 00:00:00 2001 From: bill bittner Date: Thu, 26 Jul 2018 18:40:46 -0700 Subject: [PATCH 09/14] added async await for dimension processing --- .../controllers/api/claim/publish/publish.js | 14 +++++---- server/models/utils/createFileRecordData.js | 30 ++++++++++++------- 2 files changed, 27 insertions(+), 17 deletions(-) diff --git a/server/controllers/api/claim/publish/publish.js b/server/controllers/api/claim/publish/publish.js index 425c3b50..5f0d01a1 100644 --- a/server/controllers/api/claim/publish/publish.js +++ b/server/controllers/api/claim/publish/publish.js @@ -37,16 +37,18 @@ const publish = (publishParams, fileName, fileType) => { logger.debug(`certificateId: ${certificateId}`); }) .then(() => { - const { name, claim_id: claimId } = publishParams; - // create the File record - const fileRecord = createFileRecordDataAfterPublish(fileName, fileType, publishParams, publishResults); - // create the Claim record - const claimRecord = createClaimRecordDataAfterPublish(certificateId, channelName, fileName, fileType, publishParams, publishResults); + return Promise.all([ + createFileRecordDataAfterPublish(fileName, fileType, publishParams, publishResults), + createClaimRecordDataAfterPublish(certificateId, channelName, fileName, fileType, publishParams, publishResults), + ]); + }) + .then(([fileRecord, claimRecord]) => { + // upsert the records + const {name, claim_id: claimId} = publishParams; const upsertCriteria = { name, claimId, }; - // upsert the records return Promise.all([ db.upsert(db.File, fileRecord, upsertCriteria, 'File'), db.upsert(db.Claim, claimRecord, upsertCriteria, 'Claim'), diff --git a/server/models/utils/createFileRecordData.js b/server/models/utils/createFileRecordData.js index 60ed87d4..d74f7242 100644 --- a/server/models/utils/createFileRecordData.js +++ b/server/models/utils/createFileRecordData.js @@ -1,7 +1,8 @@ const logger = require('winston'); -const sizeOf = require('image-size'); +const sizeOfImage = require('image-size'); +const sizeOfVideo = require('get-video-dimensions'); -const getFileDimensions = (fileType, filePath) => { +async function getFileDimensions (fileType, filePath) { let height = 0; let width = 0; switch (fileType) { @@ -10,12 +11,16 @@ const getFileDimensions = (fileType, filePath) => { case 'image/png': case 'image/gif': logger.debug('creating File data for an image'); - const dimensions = sizeOf(filePath); - height = dimensions.height; - width = dimensions.width; + const imageDimensions = sizeOfImage(filePath); + height = imageDimensions.height; + width = imageDimensions.width; break; case 'video/mp4': logger.debug('creating File data for a video'); + const videoDimensions = await sizeOfVideo(filePath); + logger.debug('video dimensions', videoDimensions); + height = videoDimensions.height; + width = videoDimensions.width; break; default: logger.error('unable to create File data for unspported file type:', fileType); @@ -25,9 +30,9 @@ const getFileDimensions = (fileType, filePath) => { height, width, }; -}; +} -const createFileRecordDataAfterGet = (resolveResult, getResult) => { +async function createFileRecordDataAfterGet (resolveResult, getResult) { const { name, claimId, @@ -43,7 +48,7 @@ const createFileRecordDataAfterGet = (resolveResult, getResult) => { const { height: fileHeight, width: fileWidth, - } = getFileDimensions(fileType, filePath); + } = await getFileDimensions(fileType, filePath); return { name, @@ -57,7 +62,7 @@ const createFileRecordDataAfterGet = (resolveResult, getResult) => { }; }; -const createFileRecordDataAfterPublish = (fileName, fileType, publishParams, publishResults) => { +async function createFileRecordDataAfterPublish (fileName, fileType, publishParams, publishResults) { const { name, file_path: filePath, @@ -69,7 +74,10 @@ const createFileRecordDataAfterPublish = (fileName, fileType, publishParams, pub nout, } = publishResults; - const { height: fileHeight, width: fileWidth } = getFileDimensions(fileType, filePath); + const { + height: fileHeight, + width: fileWidth, + } = await getFileDimensions(fileType, filePath); return { name, @@ -81,7 +89,7 @@ const createFileRecordDataAfterPublish = (fileName, fileType, publishParams, pub filePath, fileType, }; -}; +} module.exports = { createFileRecordDataAfterGet, -- 2.45.3 From 41ccf0637067c420eacbeec0cd0bcbeb25c84c2a Mon Sep 17 00:00:00 2001 From: bill bittner Date: Fri, 27 Jul 2018 09:58:00 -0700 Subject: [PATCH 10/14] added imagemagic and created media processing wrapper modules --- package-lock.json | 5 +++ package.json | 1 + server/models/utils/createFileRecordData.js | 38 ++------------------- server/utils/getMediaDimensions.js | 30 ++++++++++++++++ server/utils/imageProcessing.js | 29 ++++++++++++++++ server/utils/videoProcessing.js | 11 ++++++ 6 files changed, 79 insertions(+), 35 deletions(-) create mode 100644 server/utils/getMediaDimensions.js create mode 100644 server/utils/imageProcessing.js create mode 100644 server/utils/videoProcessing.js diff --git a/package-lock.json b/package-lock.json index 543859b4..38f430f1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4395,6 +4395,11 @@ "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.6.3.tgz", "integrity": "sha512-47xSUiQioGaB96nqtp5/q55m0aBQSQdyIloMOc/x+QVTDZLNmXE892IIDrJ0hM1A5vcNUDD5tDffkSP5lCaIIA==" }, + "imagemagick": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/imagemagick/-/imagemagick-0.1.3.tgz", + "integrity": "sha1-dIPOoJO02fLi85aFetyIIbU3xWo=" + }, "import-lazy": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", diff --git a/package.json b/package.json index 85da362c..545741e1 100644 --- a/package.json +++ b/package.json @@ -40,6 +40,7 @@ "get-video-dimensions": "^1.0.0", "helmet": "^3.8.1", "image-size": "^0.6.3", + "imagemagick": "^0.1.3", "module-alias": "^2.0.6", "mysql2": "^1.3.5", "passport": "^0.4.0", diff --git a/server/models/utils/createFileRecordData.js b/server/models/utils/createFileRecordData.js index d74f7242..aa0802cf 100644 --- a/server/models/utils/createFileRecordData.js +++ b/server/models/utils/createFileRecordData.js @@ -1,36 +1,4 @@ -const logger = require('winston'); -const sizeOfImage = require('image-size'); -const sizeOfVideo = require('get-video-dimensions'); - -async function getFileDimensions (fileType, filePath) { - let height = 0; - let width = 0; - switch (fileType) { - case 'image/jpeg': - case 'image/jpg': - case 'image/png': - case 'image/gif': - logger.debug('creating File data for an image'); - const imageDimensions = sizeOfImage(filePath); - height = imageDimensions.height; - width = imageDimensions.width; - break; - case 'video/mp4': - logger.debug('creating File data for a video'); - const videoDimensions = await sizeOfVideo(filePath); - logger.debug('video dimensions', videoDimensions); - height = videoDimensions.height; - width = videoDimensions.width; - break; - default: - logger.error('unable to create File data for unspported file type:', fileType); - break; - } - return { - height, - width, - }; -} +const getMediaDimensions = require('../../utils/getMediaDimensions.js'); async function createFileRecordDataAfterGet (resolveResult, getResult) { const { @@ -48,7 +16,7 @@ async function createFileRecordDataAfterGet (resolveResult, getResult) { const { height: fileHeight, width: fileWidth, - } = await getFileDimensions(fileType, filePath); + } = await getMediaDimensions(fileType, filePath); return { name, @@ -77,7 +45,7 @@ async function createFileRecordDataAfterPublish (fileName, fileType, publishPara const { height: fileHeight, width: fileWidth, - } = await getFileDimensions(fileType, filePath); + } = await getMediaDimensions(fileType, filePath); return { name, diff --git a/server/utils/getMediaDimensions.js b/server/utils/getMediaDimensions.js new file mode 100644 index 00000000..ac8d2011 --- /dev/null +++ b/server/utils/getMediaDimensions.js @@ -0,0 +1,30 @@ +const logger = require('winston'); +const { getImageHeightAndWidth } = require('./imageProcessing'); +const { getVideoHeightAndWidth } = require('./utils/videoProcessing'); + +async function getMediaDimensions (fileType, filePath) { + let height = 0; + let width = 0; + switch (fileType) { + case 'image/jpeg': + case 'image/jpg': + case 'image/png': + case 'image/gif': + logger.debug('creating File data for an image'); + [ height, width ] = await getImageHeightAndWidth(filePath); + break; + case 'video/mp4': + logger.debug('creating File data for a video'); + [ height, width ] = await getVideoHeightAndWidth(filePath); + break; + default: + logger.error('unable to create File data for unspported file type:', fileType); + break; + } + return { + height, + width, + }; +} + +module.exports = getMediaDimensions; diff --git a/server/utils/imageProcessing.js b/server/utils/imageProcessing.js new file mode 100644 index 00000000..9a93c75e --- /dev/null +++ b/server/utils/imageProcessing.js @@ -0,0 +1,29 @@ +const im = require('imagemagick'); + +const getImageMetadata = (filePath) => { + return im.readMetadata(filePath, (err, metadata) => { + if (err) throw err; + return metadata; + }); +}; + +const getImageDetails = (filePath) => { + return im.identify(filePath, (err, details) => { + if (err) throw err; + return details; + }); +}; + +const getImageHeightAndWidth = (filePath) => { + return im.identify(filePath, (err, details) => { + if (err) throw err; + const { height, width } = details; + return [height, width]; + }); +}; + +module.exports = { + getImageMetadata, + getImageDetails, + getImageHeightAndWidth, +}; diff --git a/server/utils/videoProcessing.js b/server/utils/videoProcessing.js new file mode 100644 index 00000000..508f6d10 --- /dev/null +++ b/server/utils/videoProcessing.js @@ -0,0 +1,11 @@ +const getVideoDimensions = require('get-video-dimensions'); + +async function getVideoHeightAndWidth (filePath) { + const videoDimensions = await getVideoDimensions(filePath); + const { height, width } = videoDimensions; + return [ height, width ]; +} + +module.exports = { + getVideoHeightAndWidth, +}; -- 2.45.3 From 27eddbe42ebae63ea6c0162a52537c22bf9c339b Mon Sep 17 00:00:00 2001 From: bill bittner Date: Fri, 27 Jul 2018 10:43:43 -0700 Subject: [PATCH 11/14] wrapped imagemagic functions in promises --- README.md | 34 +++++++++++++++++------------- server/utils/getMediaDimensions.js | 2 +- server/utils/imageProcessing.js | 32 +++++++++++++++++++--------- 3 files changed, 42 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index d6fb1f7a..cf970e97 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,11 @@ To get started running your own version of spee.ch, visit [lbryio/www.spee.ch](h npm install spee.ch --save ``` +### Dependenceis +Install the following programs: +* [imagemagick](https://www.imagemagick.org/) +* [ffmpeg](https://www.ffmpeg.org/) + ## Development * the `server/` folder contains all of the server code * `index.js` is the entry point for the server. It creates the [express app](https://expressjs.com/), requires the routes, syncs the database, and starts the server listening on the `PORT` designated in the config file. @@ -23,21 +28,7 @@ npm install spee.ch --save * To run only tests that do not require LBC, run `npm run test:no-lbc` ## API - -#### GET -* /api/claim/resolve/:name/:claimId - * example: `curl https://spee.ch/api/claim/resolve/doitlive/xyz` -* /api/claim/list/:name - * example: `curl https://spee.ch/api/claim/list/doitlive` -* /api/claim/availability/:name - * returns the name if it is available - * example: `curl https://spee.ch/api/claim/availability/doitlive` -* /api/channel/availability/:name - * returns the name if it is available - * example: `curl https://spee.ch/api/channel/availability/@CoolChannel` - -#### POST -* /api/claim/publish +* _(post)_ /api/claim/publish * example: `curl -F 'name=MyPictureName' -F 'file=@/path/to/myPicture.jpeg' https://spee.ch/api/claim/publish` * Parameters: * `name` (required) @@ -49,6 +40,16 @@ npm install spee.ch --save * `thumbnail` url to thumbnail image, for .mp4 uploads only (optional) * `channelName`(optional) * `channelPassword` (optional,; required if `channelName` is provided) +* _(get)_ /api/claim/resolve/:name/:claimId + * example: `curl https://spee.ch/api/claim/resolve/doitlive/xyz` +* _(get)_ /api/claim/list/:name + * example: `curl https://spee.ch/api/claim/list/doitlive` +* _(get)_ /api/claim/availability/:name + * returns the name if it is available + * example: `curl https://spee.ch/api/claim/availability/doitlive` +* _(get)_ /api/channel/availability/:name + * returns the name if it is available + * example: `curl https://spee.ch/api/channel/availability/@CoolChannel` ## Bugs If you find a bug or experience a problem, please report your issue here on github and find us in the lbry discord! @@ -69,4 +70,7 @@ Issues with spee.ch strong familiarity with the spee.ch code base and how the lb Issues with lbry (e.g. the spee.ch wallet, lbrynet configuration, etc.) that require strong familiarity with the lbry daemon and/or network to fix. Generally these issues are best suited for the lbry protocol team but are placed in this repo because of they are part of the spee.ch implementation ### Stack +* node +* mysql +* react diff --git a/server/utils/getMediaDimensions.js b/server/utils/getMediaDimensions.js index ac8d2011..fc5e79a1 100644 --- a/server/utils/getMediaDimensions.js +++ b/server/utils/getMediaDimensions.js @@ -1,6 +1,6 @@ const logger = require('winston'); const { getImageHeightAndWidth } = require('./imageProcessing'); -const { getVideoHeightAndWidth } = require('./utils/videoProcessing'); +const { getVideoHeightAndWidth } = require('./videoProcessing'); async function getMediaDimensions (fileType, filePath) { let height = 0; diff --git a/server/utils/imageProcessing.js b/server/utils/imageProcessing.js index 9a93c75e..328c661e 100644 --- a/server/utils/imageProcessing.js +++ b/server/utils/imageProcessing.js @@ -1,24 +1,36 @@ const im = require('imagemagick'); const getImageMetadata = (filePath) => { - return im.readMetadata(filePath, (err, metadata) => { - if (err) throw err; - return metadata; + return new Promise((resolve, reject) => { + im.readMetadata(filePath, (err, metadata) => { + if (err) { + reject(err); + } + resolve(metadata); + }); }); }; const getImageDetails = (filePath) => { - return im.identify(filePath, (err, details) => { - if (err) throw err; - return details; + return new Promise((resolve, reject) => { + im.identify(filePath, (err, details) => { + if (err) { + reject(err); + } + resolve(details); + }); }); }; const getImageHeightAndWidth = (filePath) => { - return im.identify(filePath, (err, details) => { - if (err) throw err; - const { height, width } = details; - return [height, width]; + return new Promise((resolve, reject) => { + im.identify(filePath, (err, details) => { + if (err) { + reject(err); + } + const { height, width } = details; + resolve([height, width]); + }); }); }; -- 2.45.3 From 0037addcda85c4058dcd1de826f1e8d5d96f662b Mon Sep 17 00:00:00 2001 From: bill bittner Date: Fri, 27 Jul 2018 11:05:10 -0700 Subject: [PATCH 12/14] updated the publish logic --- ...ublishParams.js => createPublishParams.js} | 14 +++++--- server/controllers/api/claim/publish/index.js | 36 ++++++++++++------- 2 files changed, 34 insertions(+), 16 deletions(-) rename server/controllers/api/claim/publish/{createBasicPublishParams.js => createPublishParams.js} (68%) diff --git a/server/controllers/api/claim/publish/createBasicPublishParams.js b/server/controllers/api/claim/publish/createPublishParams.js similarity index 68% rename from server/controllers/api/claim/publish/createBasicPublishParams.js rename to server/controllers/api/claim/publish/createPublishParams.js index 6ab4acd8..facdc32f 100644 --- a/server/controllers/api/claim/publish/createBasicPublishParams.js +++ b/server/controllers/api/claim/publish/createPublishParams.js @@ -1,8 +1,7 @@ const logger = require('winston'); const { details, publishing } = require('@config/siteConfig'); -const createBasicPublishParams = (filePath, name, title, description, license, nsfw, thumbnail) => { - logger.debug(`Creating Publish Parameters`); +const createPublishParams = (filePath, name, title, description, license, nsfw, thumbnail, channelName, channelClaimId) => { // provide defaults for title if (title === null || title.trim() === '') { title = name; @@ -15,7 +14,7 @@ const createBasicPublishParams = (filePath, name, title, description, license, n if (license === null || license.trim() === '') { license = ' '; // default to empty string } - // create the publish params + // create the basic publish params const publishParams = { name, file_path: filePath, @@ -34,8 +33,15 @@ const createBasicPublishParams = (filePath, name, title, description, license, n if (thumbnail) { publishParams['metadata']['thumbnail'] = thumbnail; } + // add channel details if publishing to a channel + if (channelName && channelClaimId) { + publishParams['channel_name'] = channelName; + publishParams['channel_id'] = channelClaimId; + } + // log params logger.debug('publish params:', publishParams); + // return return publishParams; }; -module.exports = createBasicPublishParams; +module.exports = createPublishParams; diff --git a/server/controllers/api/claim/publish/index.js b/server/controllers/api/claim/publish/index.js index b43995f5..c436b0b6 100644 --- a/server/controllers/api/claim/publish/index.js +++ b/server/controllers/api/claim/publish/index.js @@ -9,12 +9,14 @@ const { handleErrorResponse } = require('../../../utils/errorHandlers.js'); const checkClaimAvailability = require('../availability/checkClaimAvailability.js'); const publish = require('./publish.js'); -const createBasicPublishParams = require('./createBasicPublishParams.js'); +const createPublishParams = require('./createPublishParams.js'); const createThumbnailPublishParams = require('./createThumbnailPublishParams.js'); const parsePublishApiRequestBody = require('./parsePublishApiRequestBody.js'); const parsePublishApiRequestFiles = require('./parsePublishApiRequestFiles.js'); const authenticateUser = require('./authentication.js'); +const CLAIM_TAKEN = 'CLAIM_TAKEN'; + /* route to publish a claim through the daemon @@ -50,18 +52,22 @@ const claimPublish = ({ body, files, headers, ip, originalUrl, user, tor }, res) return res.status(400).json({success: false, message: error.message}); } // check channel authorization - Promise - .all([ - authenticateUser(channelName, channelId, channelPassword, user), - checkClaimAvailability(name), - createBasicPublishParams(filePath, name, title, description, license, nsfw, thumbnail), - createThumbnailPublishParams(thumbnailFilePath, name, license, nsfw), - ]) - .then(([{channelName, channelClaimId}, validatedClaimName, publishParams, thumbnailPublishParams]) => { + authenticateUser(channelName, channelId, channelPassword, user) + .then(({ channelName, channelClaimId }) => { // add channel details to the publish params - if (channelName && channelClaimId) { - publishParams['channel_name'] = channelName; - publishParams['channel_id'] = channelClaimId; + + return Promise.all([ + checkClaimAvailability(name), + createPublishParams(filePath, name, title, description, license, nsfw, thumbnail, channelName, channelClaimId), + createThumbnailPublishParams(thumbnailFilePath, name, license, nsfw), + ]) + }) + .then(([ claimAvailable, publishParams, thumbnailPublishParams ]) => { + if (!claimAvailabile) { + throw { + name: CLAIM_TAKEN, + message: 'That claim name is already taken' + }; } // publish the thumbnail, if one exists if (thumbnailPublishParams) { @@ -87,6 +93,12 @@ const claimPublish = ({ body, files, headers, ip, originalUrl, user, tor }, res) sendGATimingEvent('end-to-end', 'publish', fileType, gaStartTime, Date.now()); }) .catch(error => { + if (error.name = CLAIM_TAKEN) { + res.status(400).json({ + success: false, + message: error.message, + }); + } handleErrorResponse(originalUrl, ip, error, res); }); }; -- 2.45.3 From 3a46a3714eb12302e408545307c34d0de0f4442b Mon Sep 17 00:00:00 2001 From: bill bittner Date: Fri, 27 Jul 2018 12:31:08 -0700 Subject: [PATCH 13/14] updated publish flow and returned to image-size --- .../api/claim/publish/authentication.js | 51 +++++++++++-------- server/controllers/api/claim/publish/index.js | 4 +- server/utils/imageProcessing.js | 18 +++---- 3 files changed, 40 insertions(+), 33 deletions(-) diff --git a/server/controllers/api/claim/publish/authentication.js b/server/controllers/api/claim/publish/authentication.js index d41902ef..38bed36e 100644 --- a/server/controllers/api/claim/publish/authentication.js +++ b/server/controllers/api/claim/publish/authentication.js @@ -47,29 +47,38 @@ const authenticateChannelCredentials = (channelName, channelId, userPassword) => }; const authenticateUser = (channelName, channelId, channelPassword, user) => { - // case: no channelName or channel Id are provided (anonymous), regardless of whether user token is provided - if (!channelName && !channelId) { - return { - channelName : null, - channelClaimId: null, - }; - } - // case: channelName or channel Id are provided with user token - if (user) { - if (channelName && channelName !== user.channelName) { - throw new Error('the provided channel name does not match user credentials'); + return new Promise((resolve, reject) => { + // case: no channelName or channel Id are provided (anonymous), regardless of whether user token is provided + if (!channelName && !channelId) { + resolve({ + channelName : null, + channelClaimId: null, + }); + return; } - if (channelId && channelId !== user.channelClaimId) { - throw new Error('the provided channel id does not match user credentials'); + // case: channelName or channel Id are provided with user token + if (user) { + if (channelName && channelName !== user.channelName) { + reject(new Error('the provided channel name does not match user credentials')); + return; + } + if (channelId && channelId !== user.channelClaimId) { + reject(new Error('the provided channel id does not match user credentials')); + return; + } + resolve({ + channelName : user.channelName, + channelClaimId: user.channelClaimId, + }); + return; } - return { - channelName : user.channelName, - channelClaimId: user.channelClaimId, - }; - } - // case: channelName or channel Id are provided with password instead of user token - if (!channelPassword) throw new Error('no channel password provided'); - return authenticateChannelCredentials(channelName, channelId, channelPassword); + // case: channelName or channel Id are provided with password instead of user token + if (!channelPassword) { + reject(new Error('no channel password provided')); + return; + } + resolve(authenticateChannelCredentials(channelName, channelId, channelPassword)); + }); }; module.exports = authenticateUser; diff --git a/server/controllers/api/claim/publish/index.js b/server/controllers/api/claim/publish/index.js index c436b0b6..6cf726f3 100644 --- a/server/controllers/api/claim/publish/index.js +++ b/server/controllers/api/claim/publish/index.js @@ -54,8 +54,6 @@ const claimPublish = ({ body, files, headers, ip, originalUrl, user, tor }, res) // check channel authorization authenticateUser(channelName, channelId, channelPassword, user) .then(({ channelName, channelClaimId }) => { - // add channel details to the publish params - return Promise.all([ checkClaimAvailability(name), createPublishParams(filePath, name, title, description, license, nsfw, thumbnail, channelName, channelClaimId), @@ -63,7 +61,7 @@ const claimPublish = ({ body, files, headers, ip, originalUrl, user, tor }, res) ]) }) .then(([ claimAvailable, publishParams, thumbnailPublishParams ]) => { - if (!claimAvailabile) { + if (!claimAvailable) { throw { name: CLAIM_TAKEN, message: 'That claim name is already taken' diff --git a/server/utils/imageProcessing.js b/server/utils/imageProcessing.js index 328c661e..370530f6 100644 --- a/server/utils/imageProcessing.js +++ b/server/utils/imageProcessing.js @@ -1,8 +1,9 @@ -const im = require('imagemagick'); +const imageMagick = require('imagemagick'); +const sizeOf = require('image-size'); const getImageMetadata = (filePath) => { return new Promise((resolve, reject) => { - im.readMetadata(filePath, (err, metadata) => { + imageMagick.readMetadata(filePath, (err, metadata) => { if (err) { reject(err); } @@ -13,7 +14,7 @@ const getImageMetadata = (filePath) => { const getImageDetails = (filePath) => { return new Promise((resolve, reject) => { - im.identify(filePath, (err, details) => { + imageMagick.identify(filePath, (err, details) => { if (err) { reject(err); } @@ -24,13 +25,12 @@ const getImageDetails = (filePath) => { const getImageHeightAndWidth = (filePath) => { return new Promise((resolve, reject) => { - im.identify(filePath, (err, details) => { - if (err) { - reject(err); - } - const { height, width } = details; + try { + const { height, width } = sizeOf(filePath); resolve([height, width]); - }); + } catch (error) { + reject(error); + } }); }; -- 2.45.3 From 4293e445a698963526029827cc3b5ee2c6885389 Mon Sep 17 00:00:00 2001 From: bill bittner Date: Fri, 27 Jul 2018 12:39:09 -0700 Subject: [PATCH 14/14] updated readme --- README.md | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index cf970e97..c883e6b8 100644 --- a/README.md +++ b/README.md @@ -10,9 +10,9 @@ npm install spee.ch --save ``` ### Dependenceis -Install the following programs: -* [imagemagick](https://www.imagemagick.org/) -* [ffmpeg](https://www.ffmpeg.org/) +Make sure the following are installed +* [imagemagick](https://www.imagemagick.org/script/download.php) +* [ffmpeg](https://www.ffmpeg.org/download.html) ## Development * the `server/` folder contains all of the server code @@ -70,7 +70,13 @@ Issues with spee.ch strong familiarity with the spee.ch code base and how the lb Issues with lbry (e.g. the spee.ch wallet, lbrynet configuration, etc.) that require strong familiarity with the lbry daemon and/or network to fix. Generally these issues are best suited for the lbry protocol team but are placed in this repo because of they are part of the spee.ch implementation ### Stack -* node -* mysql -* react +* server + * [mysql](https://www.mysql.com/) + * [express](https://www.npmjs.com/package/express) + * [node](https://nodejs.org/) + * [lbry](https://github.com/lbryio/lbry) + * [imagemagick](https://www.imagemagick.org/) + * [ffmpeg](https://www.ffmpeg.org/) +* client + * [react](https://reactjs.org/) -- 2.45.3