From 1188d73f5d73bb8e4f9cdecb0da0c08c13a22495 Mon Sep 17 00:00:00 2001 From: bill bittner Date: Mon, 26 Jun 2017 10:02:14 -0700 Subject: [PATCH 1/6] refactored publish controller and routes --- config/production.json | 4 +- controllers/publishController.js | 57 ++++------------------------- helpers/libraries/lbryApi.js | 4 +- helpers/libraries/publishHelpers.js | 27 ++++++++++++++ package.json | 1 + routes/api-routes.js | 36 ++++++++++++++++++ routes/sockets-routes.js | 21 +++++++++-- uploadTest.html | 17 +++++++++ 8 files changed, 110 insertions(+), 57 deletions(-) create mode 100644 helpers/libraries/publishHelpers.js create mode 100644 uploadTest.html diff --git a/config/production.json b/config/production.json index 7e7e70bb..56fde915 100644 --- a/config/production.json +++ b/config/production.json @@ -1,9 +1,9 @@ { "WalletConfig": { - "lbryAddress": "none" + "LbryAddress": "none" }, "AnalyticsConfig":{ - "googleId": "UA-60403362-2" + "GoogleId": "UA-60403362-2" }, "Database": { "MySqlConnectionUri": "none", diff --git a/controllers/publishController.js b/controllers/publishController.js index abf3dca8..39410804 100644 --- a/controllers/publishController.js +++ b/controllers/publishController.js @@ -1,32 +1,8 @@ const fs = require('fs'); const logger = require('winston'); const lbryApi = require('../helpers/libraries/lbryApi.js'); -const config = require('config'); -const walledAddress = config.get('WalletConfig.lbryAddress'); -const errorHandlers = require('../helpers/libraries/errorHandlers.js'); const db = require('../models'); -function createPublishParams (claim, filePath, license, nsfw) { - logger.debug(`Creating Publish Parameters for "${claim}"`); - const publishParams = { - name : claim, - file_path: filePath, - bid : 0.01, - metadata : { - description: `${claim} published via spee.ch`, - title : claim, - author : 'spee.ch', - language : 'en', - license, - nsfw, - }, - claim_address : walledAddress, - change_address: walledAddress, - }; - logger.debug('publishParams:', publishParams); - return publishParams; -} - function deleteTemporaryFile (filePath) { fs.unlink(filePath, err => { if (err) throw err; @@ -49,51 +25,34 @@ function upsert (Model, values, condition) { } module.exports = { - publish (name, fileName, filePath, fileType, license, nsfw, socket, visitor) { - console.log('nsfw:', nsfw); - // validate nsfw - if (typeof nsfw === 'string') { - nsfw = (nsfw.toLowerCase() === 'true'); - } - // update the client - socket.emit('publish-status', 'Your image is being published (this might take a second)...'); - // send to analytics - visitor.event('Publish Route', 'Publish Request', filePath).send(); - // create the publish object - const publishParams = createPublishParams(name, filePath, license, nsfw); + publish: (publishParams, fileName, fileType) => { // 1. publish the file lbryApi - .publishClaim(publishParams, fileName, fileType) + .publishClaim(publishParams) .then(result => { logger.info(`Successfully published ${fileName}`, result); - // google analytics - visitor.event('Publish Route', 'Publish Success', filePath).send(); // 2. update old record of create new one (update is in case the claim has been published before by this daemon) upsert( db.File, { - name, + name : publishParams.name, claimId : result.claim_id, outpoint: `${result.txid}:${result.nout}`, height : 0, fileName, - filePath, + filePath: publishParams.file_path, fileType, - nsfw, + nsfw : publishParams.metadata.nsfw, }, - { name, claimId: result.claim_id } + { name: publishParams.name, claimId: result.claim_id } ).catch(error => { logger.error('Sequelize findOne error', error); }); - // update client - socket.emit('publish-complete', { name, result }); }) .catch(error => { logger.error(`Error publishing ${fileName}`, error); - // google analytics - visitor.event('Publish Route', 'Publish Failure', filePath).send(); - socket.emit('publish-failure', errorHandlers.handlePublishError(error)); - deleteTemporaryFile(filePath); + // delete the local file + deleteTemporaryFile(publishParams.file_path); }); }, }; diff --git a/helpers/libraries/lbryApi.js b/helpers/libraries/lbryApi.js index 3ff86cfd..026e1eee 100644 --- a/helpers/libraries/lbryApi.js +++ b/helpers/libraries/lbryApi.js @@ -2,8 +2,8 @@ const axios = require('axios'); const logger = require('winston'); module.exports = { - publishClaim (publishParams, fileName, fileType) { - logger.debug(`Publishing claim for "${fileName}"`); + publishClaim (publishParams) { + logger.debug(`Publishing claim to "${publishParams.name}"`); const deferred = new Promise((resolve, reject) => { axios .post('http://localhost:5279/lbryapi', { diff --git a/helpers/libraries/publishHelpers.js b/helpers/libraries/publishHelpers.js new file mode 100644 index 00000000..c0f8be79 --- /dev/null +++ b/helpers/libraries/publishHelpers.js @@ -0,0 +1,27 @@ +const logger = require('winston'); + +const config = require('config'); +const walletAddress = config.get('WalletConfig.LbryAddress'); + +module.exports = { + createPublishParams (name, filePath, license, nsfw) { + logger.debug(`Creating Publish Parameters for "${name}"`); + const publishParams = { + name, + file_path: filePath, + bid : 0.01, + metadata : { + description: `${name} published via spee.ch`, + title : name, + author : 'spee.ch', + language : 'en', + license, + nsfw, + }, + claim_address : walletAddress, + change_address: walletAddress, + }; + logger.debug('publishParams:', publishParams); + return publishParams; + }, +}; diff --git a/package.json b/package.json index 1204d3e9..b4706565 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,7 @@ "axios": "^0.16.1", "body-parser": "^1.17.1", "config": "^1.26.1", + "connect-multiparty": "^2.0.0", "express": "^4.15.2", "express-handlebars": "^3.0.0", "mysql2": "^1.3.5", diff --git a/routes/api-routes.js b/routes/api-routes.js index 65e8056b..7576c2e4 100644 --- a/routes/api-routes.js +++ b/routes/api-routes.js @@ -1,6 +1,10 @@ const errorHandlers = require('../helpers/libraries/errorHandlers.js'); const lbryApi = require('../helpers/libraries/lbryApi.js'); const logger = require('winston'); +const multipart = require('connect-multiparty'); +const multipartMiddleware = multipart(); +const publishController = require('../helpers/libraries/publishController.js'); +const publishHelpers = require('../helpers/libraries/publishHelpers.js'); module.exports = app => { // route to run a claim_list request on the daemon @@ -27,4 +31,36 @@ module.exports = app => { errorHandlers.handleRequestError(error, res); }); }); + // route to run a publish request on the daemon + app.post('/api/publish', multipartMiddleware, ({ originalUrl, body, files }, res) => { + logger.debug(`POST request on ${originalUrl}`); + console.log('>> req.files:', files); + console.log(' >> req.body:', body); + const name = body.claimName; + const license = body.license; + const nsfw = body.nsfw; + const fileName = files.file1.name; + const filePath = files.file1.path; + const fileType = files.file1.type; + /* + make sure it's not a harmful file type + */ + // prepare the publish parameters + const publishParams = publishHelpers.createPublishParams(name, filePath, license, nsfw); + // publish the file + publishController + .publish(publishParams, fileName, fileType) + .then(result => { + res.status(200).json(result); + }) + .catch(error => { + errorHandlers.handleRequestError(error, res); + }); + + if (files) { + res.status(200).json({'status': 'file(s) received'}); + } else { + res.status(400).josn({'status': 'no files(s) received'}); + } + }); }; diff --git a/routes/sockets-routes.js b/routes/sockets-routes.js index 0589a58b..705d47ff 100644 --- a/routes/sockets-routes.js +++ b/routes/sockets-routes.js @@ -1,5 +1,7 @@ -const publishController = require('../controllers/publishController.js'); const logger = require('winston'); +const publishController = require('../controllers/publishController.js'); +const publishHelpers = require('../controllers/publishHelpers.js'); +const errorHandlers = require('../helpers/libraries/errorHandlers.js'); module.exports = (app, siofu, hostedContentPath, ua, googleAnalyticsId) => { const http = require('http').Server(app); @@ -7,8 +9,9 @@ module.exports = (app, siofu, hostedContentPath, ua, googleAnalyticsId) => { io.on('connection', socket => { logger.silly('a user connected via sockets'); - // create visitor record + // google analytics const visitor = ua(googleAnalyticsId, { https: true }); + visitor.event('Publish Route', 'Publish Request').send(); // attach upload listeners const uploader = new siofu(); uploader.dir = hostedContentPath; @@ -27,8 +30,18 @@ module.exports = (app, siofu, hostedContentPath, ua, googleAnalyticsId) => { uploader.on('saved', ({ file }) => { if (file.success) { logger.debug(`Client successfully uploaded ${file.name}`); - socket.emit('publish-status', 'file upload successfully completed'); - publishController.publish(file.meta.name, file.name, file.pathName, file.meta.type, file.meta.license, file.meta.nsfw, socket, visitor); + socket.emit('publish-status', 'file upload successfully completed. Your image is being published (this might take a second)...'); + // prepare the publish parameters + const publishParams = publishHelpers.createPublishParams(file.meta.name, file.pathName, file.meta.license, file.meta.nsfw); + // publish the file + publishController + .publish(publishParams, file.name, file.meta.type) + .then(result => { + socket.emit('publish-complete', { name: publishParams.name, result }); + }) + .catch(error => { + socket.emit('publish-failure', errorHandlers.handlePublishError(error)); + }); } else { logger.error(`An error occurred in uploading the client's file`); socket.emit('publish-failure', 'file uploaded, but with errors'); diff --git a/uploadTest.html b/uploadTest.html new file mode 100644 index 00000000..16e7aae4 --- /dev/null +++ b/uploadTest.html @@ -0,0 +1,17 @@ + + + + + upload + + +
+

+

+

+

+

+

+

+ + \ No newline at end of file From 5c95b5c7ece269c542f0a4fbaa7187fe898b4d19 Mon Sep 17 00:00:00 2001 From: bill bittner Date: Mon, 26 Jun 2017 10:43:35 -0700 Subject: [PATCH 2/6] route is properly pulling metadata --- config/custom-environment-variables.json | 2 +- config/default.json | 4 +-- config/development.json | 4 +-- {helpers/logging => config}/loggerSetup.js | 0 config/test.json | 4 +-- routes/api-routes.js | 36 +++++++++++++--------- routes/sockets-routes.js | 2 +- server.js | 6 ++-- 8 files changed, 32 insertions(+), 26 deletions(-) rename {helpers/logging => config}/loggerSetup.js (100%) diff --git a/config/custom-environment-variables.json b/config/custom-environment-variables.json index cb9b9aa3..be110732 100644 --- a/config/custom-environment-variables.json +++ b/config/custom-environment-variables.json @@ -1,6 +1,6 @@ { "WalletConfig": { - "lbryAddress": "LBRY_WALLET_ADDRESS" + "LbryAddress": "LBRY_WALLET_ADDRESS" }, "Database": { "MySqlConnectionUri": "MYSQL_CONNECTION_STRING" diff --git a/config/default.json b/config/default.json index 2b06f70a..546378c7 100644 --- a/config/default.json +++ b/config/default.json @@ -1,9 +1,9 @@ { "WalletConfig": { - "lbryAddress": "none" + "LbryAddress": "none" }, "AnalyticsConfig":{ - "googleId": "none" + "GoogleId": "none" }, "Database": { "MySqlConnectionUri": "none", diff --git a/config/development.json b/config/development.json index 2712bde3..38c7affe 100644 --- a/config/development.json +++ b/config/development.json @@ -1,9 +1,9 @@ { "WalletConfig": { - "lbryAddress": "none" + "LbryAddress": "none" }, "AnalyticsConfig":{ - "googleId": "UA-100747990-1" + "GoogleId": "UA-100747990-1" }, "Database": { "MySqlConnectionUri": "none", diff --git a/helpers/logging/loggerSetup.js b/config/loggerSetup.js similarity index 100% rename from helpers/logging/loggerSetup.js rename to config/loggerSetup.js diff --git a/config/test.json b/config/test.json index c20a8c16..b74d2997 100644 --- a/config/test.json +++ b/config/test.json @@ -1,9 +1,9 @@ { "WalletConfig": { - "lbryAddress": "none" + "LbryAddress": "none" }, "AnalyticsConfig":{ - "googleId": "UA-100747990-1" + "GoogleId": "UA-100747990-1" }, "Database": { "MySqlConnectionUri": "none", diff --git a/routes/api-routes.js b/routes/api-routes.js index 7576c2e4..a4dceb60 100644 --- a/routes/api-routes.js +++ b/routes/api-routes.js @@ -1,10 +1,10 @@ -const errorHandlers = require('../helpers/libraries/errorHandlers.js'); -const lbryApi = require('../helpers/libraries/lbryApi.js'); const logger = require('winston'); const multipart = require('connect-multiparty'); const multipartMiddleware = multipart(); -const publishController = require('../helpers/libraries/publishController.js'); +const publishController = require('../controllers/publishController.js'); +const lbryApi = require('../helpers/libraries/lbryApi.js'); const publishHelpers = require('../helpers/libraries/publishHelpers.js'); +const errorHandlers = require('../helpers/libraries/errorHandlers.js'); module.exports = app => { // route to run a claim_list request on the daemon @@ -35,18 +35,24 @@ module.exports = app => { app.post('/api/publish', multipartMiddleware, ({ originalUrl, body, files }, res) => { logger.debug(`POST request on ${originalUrl}`); console.log('>> req.files:', files); - console.log(' >> req.body:', body); - const name = body.claimName; - const license = body.license; - const nsfw = body.nsfw; - const fileName = files.file1.name; - const filePath = files.file1.path; - const fileType = files.file1.type; + console.log('>> req.body:', body); + const file = files.file1; + if (!file) { + res.status(500).json({ 'error': 'No file was submitted. Form submission must have key "speechFile"' }); + return; + } + const name = body.claim || file.name.substring(0, file.name.indexOf('.')); + const license = body.license || 'No License Provided'; + const nsfw = body.nsfw || true; + const fileName = file.name; + const filePath = file.path; + const fileType = file.type; /* make sure it's not a harmful file type */ // prepare the publish parameters const publishParams = publishHelpers.createPublishParams(name, filePath, license, nsfw); + console.log('publish params', publishParams); // publish the file publishController .publish(publishParams, fileName, fileType) @@ -57,10 +63,10 @@ module.exports = app => { errorHandlers.handleRequestError(error, res); }); - if (files) { - res.status(200).json({'status': 'file(s) received'}); - } else { - res.status(400).josn({'status': 'no files(s) received'}); - } + // if (files) { + // res.status(200).json({'status': 'file(s) received'}); + // } else { + // res.status(400).josn({'status': 'no files(s) received'}); + // } }); }; diff --git a/routes/sockets-routes.js b/routes/sockets-routes.js index 705d47ff..af4ecd41 100644 --- a/routes/sockets-routes.js +++ b/routes/sockets-routes.js @@ -1,6 +1,6 @@ const logger = require('winston'); const publishController = require('../controllers/publishController.js'); -const publishHelpers = require('../controllers/publishHelpers.js'); +const publishHelpers = require('../helpers/libraries/publishHelpers.js'); const errorHandlers = require('../helpers/libraries/errorHandlers.js'); module.exports = (app, siofu, hostedContentPath, ua, googleAnalyticsId) => { diff --git a/server.js b/server.js index c2aef521..8df35748 100644 --- a/server.js +++ b/server.js @@ -8,13 +8,13 @@ const config = require('config'); const ua = require('universal-analytics'); const winston = require('winston'); -const googleAnalyticsId = config.get('AnalyticsConfig.googleId'); +const googleAnalyticsId = config.get('AnalyticsConfig.GoogleId'); const hostedContentPath = config.get('Database.PublishUploadPath'); // configure logging const logLevel = config.get('Logging.LogLevel'); const logDir = config.get('Logging.LogDirectory'); -require('./helpers/logging/loggerSetup.js')(winston, logLevel, logDir); +require('./config/loggerSetup.js')(winston, logLevel, logDir); // set port const PORT = 3000; @@ -38,7 +38,7 @@ const hbs = expressHandlebars.create({ helpers : { // define any extra helpers you may need googleAnalytics () { - const googleApiKey = config.get('AnalyticsConfig.googleId'); + const googleApiKey = config.get('AnalyticsConfig.GoogleId'); return new Handlebars.SafeString( `