diff --git a/config/default.json b/config/default.json index a50953a0..2a048516 100644 --- a/config/default.json +++ b/config/default.json @@ -12,7 +12,6 @@ "PublishUploadPath": "none" }, "Logging": { - "LogLevel": "none", - "LogDirectory": "none" + "LogLevel": "none" } } \ No newline at end of file diff --git a/config/development.json b/config/development.json index 9b0e04cf..2c132e88 100644 --- a/config/development.json +++ b/config/development.json @@ -9,10 +9,9 @@ }, "Database": { "MySqlConnectionUri": "none", - "PublishUploadPath": "C:\\lbry\\speech\\hosted_content\\" + "PublishUploadPath": "C:\\Users\\Bones\\Downloads\\lbry\\" }, "Logging": { - "LogLevel": "silly", - "LogDirectory": "C:\\lbry\\speech\\logs\\" + "LogLevel": "silly" } } \ No newline at end of file diff --git a/config/loggerSetup.js b/config/loggerSetup.js index 7a0b2e41..ffd4c970 100644 --- a/config/loggerSetup.js +++ b/config/loggerSetup.js @@ -1,10 +1,4 @@ -const fs = require('fs'); - -module.exports = (winston, logLevel, logDir) => { - if (!fs.existsSync(logDir)) { - fs.mkdirSync(logDir); - } - +module.exports = (winston, logLevel) => { winston.configure({ transports: [ new (winston.transports.Console)({ @@ -15,16 +9,6 @@ module.exports = (winston, logLevel, logDir) => { handleExceptions : true, humanReadableUnhandledException: true, }), - new (winston.transports.File)({ - filename : `${logDir}/speechLogs.log`, - level : logLevel, - json : false, - timestamp : true, - colorize : true, - prettyPrint : true, - handleExceptions : true, - humanReadableUnhandledException: true, - }), ], }); diff --git a/config/production.json b/config/production.json index 848f1700..27d3fc04 100644 --- a/config/production.json +++ b/config/production.json @@ -12,7 +12,6 @@ "PublishUploadPath": "/home/lbry/Downloads/" }, "Logging": { - "LogLevel": "verbose", - "LogDirectory": "/home/lbry/Logs" + "LogLevel": "verbose" } } diff --git a/config/test.json b/config/test.json index bab71bfa..80a771a7 100644 --- a/config/test.json +++ b/config/test.json @@ -12,7 +12,6 @@ "PublishUploadPath": "/home/ubuntu/Downloads/" }, "Logging": { - "LogLevel": "debug", - "LogDirectory": "/home/ubuntu/Logs" + "LogLevel": "debug" } } diff --git a/controllers/statsController.js b/controllers/statsController.js index dee75b72..1242a86a 100644 --- a/controllers/statsController.js +++ b/controllers/statsController.js @@ -5,7 +5,7 @@ const db = require('../models'); const googleApiKey = config.get('AnalyticsConfig.GoogleId'); module.exports = { - postToStats (action, url, ipAddress, name, claimId, result) { + postToStats (action, url, ipAddress, name, claimId, fileName, fileType, nsfw, result) { logger.silly(`creating ${action} record for statistics db`); // make sure the result is a string if (result && (typeof result !== 'string')) { @@ -22,6 +22,9 @@ module.exports = { ipAddress, name, claimId, + fileName, + fileType, + nsfw, result, }) .then() @@ -73,13 +76,14 @@ module.exports = { }, }) .then(data => { - const resultHashTable = {}; + let resultHashTable = {}; let totalServe = 0; let totalPublish = 0; let totalShow = 0; let totalCount = 0; let totalSuccess = 0; let totalFailure = 0; + let percentSuccess; // sumarise the data for (let i = 0; i < data.length; i++) { let key = data[i].action + data[i].url; @@ -122,7 +126,7 @@ module.exports = { } } } - const percentSuccess = Math.round(totalSuccess / totalCount * 100); + percentSuccess = Math.round(totalSuccess / totalCount * 100); // return results resolve({ records: resultHashTable, totals: { totalServe, totalPublish, totalShow, totalCount, totalSuccess, totalFailure }, percentSuccess }); }) @@ -152,28 +156,27 @@ module.exports = { }, }) .then(data => { - const resultHashTable = {}; + let resultHashTable = {}; + let sortableArray = []; + let sortedArray; // summarise the data for (let i = 0; i < data.length; i++) { let key = `${data[i].name}#${data[i].claimId}`; - logger.debug(key); - console.log(resultHashTable[key]); if (resultHashTable[key] === undefined) { - // console.log(resultHashTable[key]); resultHashTable[key] = { count : 0, details: { - name : data[i].name, - claimId: data[i].claimId, + name : data[i].name, + claimId : data[i].claimId, + fileName: data[i].fileName, + fileType: data[i].fileType, + nsfw : data[i].nsfw, }, }; } else { - // console.log(resultHashTable[key]); resultHashTable[key]['count'] += 1; } } - // order the results - let sortableArray = []; for (let objKey in resultHashTable) { if (resultHashTable.hasOwnProperty(objKey)) { sortableArray.push([ @@ -183,13 +186,12 @@ module.exports = { } } sortableArray.sort((a, b) => { - return a[0] - b[0]; + return b[0] - a[0]; }); - const sortedArray = sortableArray.map((a) => { + sortedArray = sortableArray.map((a) => { return a[1]; }); // return results - logger.debug(sortedArray); resolve(sortedArray); }) .catch(error => { diff --git a/helpers/libraries/errorHandlers.js b/helpers/libraries/errorHandlers.js index 188a6757..a256b048 100644 --- a/helpers/libraries/errorHandlers.js +++ b/helpers/libraries/errorHandlers.js @@ -5,16 +5,16 @@ module.exports = { handleRequestError (action, originalUrl, ip, error, res) { logger.error('Request Error >>', error); if (error.response) { - postToStats(action, originalUrl, ip, null, null, error.response.data.error.messsage); + postToStats(action, originalUrl, ip, null, null, null, null, null, error.response.data.error.messsage); res.status(error.response.status).send(error.response.data.error.message); } else if (error.code === 'ECONNREFUSED') { - postToStats(action, originalUrl, ip, null, null, 'Connection refused. The daemon may not be running.'); + postToStats(action, originalUrl, ip, null, null, null, null, null, 'Connection refused. The daemon may not be running.'); res.status(503).send('Connection refused. The daemon may not be running.'); } else if (error.message) { - postToStats(action, originalUrl, ip, null, null, error); + postToStats(action, originalUrl, ip, null, null, null, null, null, error); res.status(400).send(error.message); } else { - postToStats(action, originalUrl, ip, null, null, error); + postToStats(action, originalUrl, ip, null, null, null, null, null, error); res.status(400).send(error); } }, diff --git a/models/stats.js b/models/stats.js index 00fef482..a18ee472 100644 --- a/models/stats.js +++ b/models/stats.js @@ -1,4 +1,4 @@ -module.exports = (sequelize, { STRING, TEXT }) => { +module.exports = (sequelize, { STRING, BOOLEAN, TEXT }) => { const Stats = sequelize.define( 'Stats', { @@ -13,17 +13,26 @@ module.exports = (sequelize, { STRING, TEXT }) => { ipAddress: { type : STRING, allowNull: true, - default : null, }, name: { type : STRING, allowNull: true, - default : null, }, claimId: { type : STRING, allowNull: true, - default : null, + }, + fileName: { + type : STRING, + allowNull: true, + }, + fileType: { + type : STRING, + allowNull: true, + }, + nsfw: { + type : BOOLEAN, + allowNull: true, }, result: { type : TEXT('long'), diff --git a/public/assets/css/componentStyle.css b/public/assets/css/componentStyle.css index a837dabd..a7735c32 100644 --- a/public/assets/css/componentStyle.css +++ b/public/assets/css/componentStyle.css @@ -12,6 +12,29 @@ margin: 2px 5px 2px 5px; } +/* publish */ +#drop-zone { + border: 1px dashed lightgrey; + padding: 1em; + height: 6em; +} + +#asset-preview-holder { + width: 100%; + margin-bottom: 1em; +} + +.snapshot-generator { + display: block; + height: 1px; + left: 0; + object-fit: contain; + position: fixed; + top: 0; + width: 1px; + z-index: -1; +} + /* show routes */ .show-asset { width: 100%; @@ -53,7 +76,14 @@ button.copy-button { vertical-align: top; } -/* learn more */ +/* trending claims */ +.asset-trending { + width: 21%; + margin: 2%; + float: left; +} + +/* learn more */ .learn-more { text-align: center; margin-top: 2px; @@ -115,29 +145,6 @@ button.copy-button { list-style-type: none; } -/* publish */ -#drop-zone { - border: 1px dashed lightgrey; - padding: 1em; - height: 6em; -} - -#asset-preview-holder { - width: 100%; - margin-bottom: 1em; -} - -.snapshot-generator { - display: block; - height: 1px; - left: 0; - object-fit: contain; - position: fixed; - top: 0; - width: 1px; - z-index: -1; -} - /* meme */ canvas { background-color: white; @@ -145,13 +152,6 @@ canvas { height: auto; } -.meme-fodder-img { - width: 21%; - padding: 0px; - margin: 2% 4% 2% 0px; - float: left; -} - /* statistics */ .totals-row { border-top: 1px solid grey; diff --git a/public/assets/css/allStyle.css b/public/assets/css/generalStyle.css similarity index 96% rename from public/assets/css/allStyle.css rename to public/assets/css/generalStyle.css index ee0991fa..668ba44c 100644 --- a/public/assets/css/allStyle.css +++ b/public/assets/css/generalStyle.css @@ -91,6 +91,13 @@ h4 { /* other */ +.asset-small { + height: 200px; + padding: 0px; + margin: 10px; + float: left; +} + input { padding: 0.3em; } diff --git a/routes/api-routes.js b/routes/api-routes.js index 5f8327de..75442175 100644 --- a/routes/api-routes.js +++ b/routes/api-routes.js @@ -24,7 +24,7 @@ module.exports = app => { lbryApi .getClaimsList(params.name) .then(claimsList => { - postToStats('serve', originalUrl, ip, null, null, 'success'); + postToStats('serve', originalUrl, ip, null, null, null, null, 'success'); res.status(200).json(claimsList); }) .catch(error => { @@ -56,7 +56,7 @@ module.exports = app => { lbryApi .resolveUri(params.uri) .then(resolvedUri => { - postToStats('serve', originalUrl, ip, null, null, 'success'); + postToStats('serve', originalUrl, ip, null, null, null, null, 'success'); res.status(200).json(resolvedUri); }) .catch(error => { @@ -76,7 +76,7 @@ module.exports = app => { try { validateFile(file, name, license, nsfw); } catch (error) { - postToStats('publish', originalUrl, ip, null, null, error.message); + postToStats('publish', originalUrl, ip, null, null, null, null, error.message); logger.debug('rejected >>', error.message); res.status(400).send(error.message); return; @@ -91,7 +91,7 @@ module.exports = app => { publishController .publish(publishParams, fileName, fileType) .then(result => { - postToStats('publish', originalUrl, ip, null, null, 'success'); + postToStats('publish', originalUrl, ip, null, null, null, null, 'success'); res.status(200).json(result); }) .catch(error => { diff --git a/routes/home-routes.js b/routes/home-routes.js index d4d51127..d3632aa0 100644 --- a/routes/home-routes.js +++ b/routes/home-routes.js @@ -1,17 +1,25 @@ const logger = require('winston'); -const { postToStats } = require('../controllers/statsController.js'); +const { postToStats, getTrendingClaims } = require('../controllers/statsController.js'); +const errorHandlers = require('../helpers/libraries/errorHandlers.js'); module.exports = app => { // route for the home page app.get('/', ({ headers, ip, originalUrl }, res) => { - // send response - res.status(200).render('index'); + const startDate = new Date(); + startDate.setDate(startDate.getDate() - 1); + getTrendingClaims(startDate) + .then(result => { + res.status(200).render('index', { trendingAssets: result }); + }) + .catch(error => { + errorHandlers.handleRequestError(error, res); + }); }); // a catch-all route if someone visits a page that does not exist app.use('*', ({ originalUrl, ip }, res) => { logger.error(`404 on ${originalUrl}`); // post to stats - postToStats('show', originalUrl, ip, null, null, 'Error: 404'); + postToStats('show', originalUrl, ip, null, null, null, null, null, 'Error: 404'); // send response res.status(404).render('fourOhFour'); }); diff --git a/routes/serve-routes.js b/routes/serve-routes.js index 4a6bf307..d8608d61 100644 --- a/routes/serve-routes.js +++ b/routes/serve-routes.js @@ -52,14 +52,14 @@ module.exports = (app) => { if (headers['accept']) { // note: added b/c some requests errored out due to no accept param in header const mimetypes = headers['accept'].split(','); if (mimetypes.includes('text/html')) { - postToStats('show', originalUrl, ip, fileInfo.name, fileInfo.claimId, 'success'); + postToStats('show', originalUrl, ip, fileInfo.name, fileInfo.claimId, fileInfo.fileName, fileInfo.fileType, fileInfo.nsfw, 'success'); res.status(200).render('showLite', { fileInfo }); } else { - postToStats('serve', originalUrl, ip, fileInfo.name, fileInfo.claimId, 'success'); + postToStats('serve', originalUrl, ip, fileInfo.name, fileInfo.claimId, fileInfo.fileName, fileInfo.fileType, fileInfo.nsfw, 'success'); serveFile(fileInfo, res); } } else { - postToStats('serve', originalUrl, ip, fileInfo.name, fileInfo.claimId, 'success'); + postToStats('serve', originalUrl, ip, fileInfo.name, fileInfo.claimId, fileInfo.fileName, fileInfo.fileType, fileInfo.nsfw, 'success'); serveFile(fileInfo, res); } }) @@ -82,14 +82,14 @@ module.exports = (app) => { if (headers['accept']) { // note: added b/c some requests errored out due to no accept param in header const mimetypes = headers['accept'].split(','); if (mimetypes.includes('text/html')) { - postToStats('show', originalUrl, ip, fileInfo.name, fileInfo.claimId, 'success'); + postToStats('show', originalUrl, ip, fileInfo.name, fileInfo.claimId, fileInfo.fileName, fileInfo.fileType, fileInfo.nsfw, 'success'); res.status(200).render('showLite', { fileInfo }); } else { - postToStats('serve', originalUrl, ip, fileInfo.name, fileInfo.claimId, 'success'); + postToStats('serve', originalUrl, ip, fileInfo.name, fileInfo.claimId, fileInfo.fileName, fileInfo.fileType, fileInfo.nsfw, 'success'); serveFile(fileInfo, res); } } else { - postToStats('serve', originalUrl, ip, fileInfo.name, fileInfo.claimId, 'success'); + postToStats('serve', originalUrl, ip, fileInfo.name, fileInfo.claimId, fileInfo.fileName, fileInfo.fileType, fileInfo.nsfw, 'success'); serveFile(fileInfo, res); } }) diff --git a/routes/show-routes.js b/routes/show-routes.js index 763822b2..8f69270a 100644 --- a/routes/show-routes.js +++ b/routes/show-routes.js @@ -27,7 +27,7 @@ module.exports = (app) => { startDate.setDate(startDate.getDate() - 1); getStatsSummary(startDate) .then(result => { - postToStats('show', originalUrl, ip, null, null, 'success'); + postToStats('show', originalUrl, ip, null, null, null, null, null, 'success'); res.status(200).render('statistics', result); }) .catch(error => { @@ -39,7 +39,7 @@ module.exports = (app) => { // get and render the content getAllClaims('meme-fodder') .then(orderedFreePublicClaims => { - postToStats('show', originalUrl, ip, null, null, 'success'); + postToStats('show', originalUrl, ip, null, null, null, null, null, 'success'); res.status(200).render('memeFodder', { claims: orderedFreePublicClaims }); }) .catch(error => { @@ -55,7 +55,7 @@ module.exports = (app) => { res.status(307).render('noClaims'); return; } - postToStats('show', originalUrl, ip, null, null, 'success'); + postToStats('show', originalUrl, ip, null, null, null, null, null, 'success'); res.status(200).render('allClaims', { claims: orderedFreePublicClaims }); }) .catch(error => { @@ -73,7 +73,7 @@ module.exports = (app) => { return; } // serve the file or the show route - postToStats('show', originalUrl, ip, fileInfo.name, fileInfo.claimId, 'success'); + postToStats('show', originalUrl, ip, fileInfo.name, fileInfo.claimId, fileInfo.fileName, fileInfo.fileType, fileInfo.nsfw, 'success'); res.status(200).render('show', { fileInfo }); }) .catch(error => { @@ -91,7 +91,7 @@ module.exports = (app) => { return; } // serve the show route - postToStats('show', originalUrl, ip, fileInfo.name, fileInfo.claimId, 'success'); + postToStats('show', originalUrl, ip, fileInfo.name, fileInfo.claimId, fileInfo.fileName, fileInfo.fileType, fileInfo.nsfw, 'success'); res.status(200).render('show', { fileInfo }); }) .catch(error => { diff --git a/routes/sockets-routes.js b/routes/sockets-routes.js index bb3d23b3..feeb0e3b 100644 --- a/routes/sockets-routes.js +++ b/routes/sockets-routes.js @@ -27,7 +27,7 @@ module.exports = (app, siofu, hostedContentPath) => { // listener for when file upload encounters an error uploader.on('error', ({ error }) => { logger.error('an error occured while uploading', error); - postToStats('publish', '/', null, null, error); + postToStats('publish', '/', null, null, null, null, error); socket.emit('publish-status', error); }); // listener for when file has been uploaded @@ -41,18 +41,18 @@ module.exports = (app, siofu, hostedContentPath) => { publishController .publish(publishParams, file.name, file.meta.type) .then(result => { - postToStats('publish', '/', null, null, 'success'); + postToStats('publish', '/', null, null, null, null, 'success'); socket.emit('publish-complete', { name: publishParams.name, result }); }) .catch(error => { error = errorHandlers.handlePublishError(error); - postToStats('publish', '/', null, null, error); + postToStats('publish', '/', null, null, null, null, error); socket.emit('publish-failure', error); }); } else { logger.error(`An error occurred in uploading the client's file`); socket.emit('publish-failure', 'File uploaded, but with errors'); - postToStats('publish', '/', null, null, 'File uploaded, but with errors'); + postToStats('publish', '/', null, null, null, null, 'File uploaded, but with errors'); // to-do: remove the file if not done automatically } }); diff --git a/server.js b/server.js index 359c99a5..332889f4 100644 --- a/server.js +++ b/server.js @@ -11,8 +11,7 @@ const hostedContentPath = config.get('Database.PublishUploadPath'); // configure logging const logLevel = config.get('Logging.LogLevel'); -const logDir = config.get('Logging.LogDirectory'); -require('./config/loggerSetup.js')(winston, logLevel, logDir); +require('./config/loggerSetup.js')(winston, logLevel); // set port const PORT = 3000; @@ -92,9 +91,13 @@ const server = require('./routes/sockets-routes.js')(app, siofu, hostedContentPa // sync sequelize // wrap the server in socket.io to intercept incoming sockets requests // start server -db.sequelize.sync().then(() => { - server.listen(PORT, () => { - winston.info('Trusting proxy?', app.get('trust proxy')); - winston.info(`Server is listening on PORT ${PORT}`); +db.sequelize.sync() + .then(() => { + server.listen(PORT, () => { + winston.info('Trusting proxy?', app.get('trust proxy')); + winston.info(`Server is listening on PORT ${PORT}`); + }); + }) + .catch((error) => { + winston.log('Error syncing sequelize db:', error); }); -}); diff --git a/views/index.handlebars b/views/index.handlebars index a698756f..7f74f50b 100644 --- a/views/index.handlebars +++ b/views/index.handlebars @@ -3,11 +3,14 @@
{{> publish}} {{> learnMore}} + {{> trending}}
+ {{> footer}} + diff --git a/views/layouts/main.handlebars b/views/layouts/main.handlebars index ee2311da..a3babda6 100644 --- a/views/layouts/main.handlebars +++ b/views/layouts/main.handlebars @@ -5,11 +5,10 @@ Spee.ch - + - {{{ body }}} {{ googleAnalytics }} diff --git a/views/memeFodder.handlebars b/views/memeFodder.handlebars index 12a1dd50..f85e883b 100644 --- a/views/memeFodder.handlebars +++ b/views/memeFodder.handlebars @@ -10,5 +10,6 @@ + \ No newline at end of file diff --git a/views/partials/asset.handlebars b/views/partials/asset.handlebars index aeda960a..157c572b 100644 --- a/views/partials/asset.handlebars +++ b/views/partials/asset.handlebars @@ -1,5 +1,5 @@
-
+
{{#ifConditional fileInfo.fileType '===' 'video/mp4'}}
{{#each claims}} - + {{/each}}
\ No newline at end of file diff --git a/views/partials/trending.handlebars b/views/partials/trending.handlebars new file mode 100644 index 00000000..3fbc585a --- /dev/null +++ b/views/partials/trending.handlebars @@ -0,0 +1,19 @@ +
+

Trending

+ {{#each trendingAssets}} + {{#if this.nsfw}} + {{else }} + {{#ifConditional this.fileType '===' 'video/mp4'}} + + {{else}} + + + + {{/ifConditional}} + {{/if}} + {{/each}} +
diff --git a/views/showLite.handlebars b/views/showLite.handlebars index b44d724a..c3477088 100644 --- a/views/showLite.handlebars +++ b/views/showLite.handlebars @@ -1,4 +1,4 @@ -
+
{{#ifConditional fileInfo.fileType '===' 'video/mp4'}}
- - - - - -