diff --git a/README.md b/README.md index 05b7c37a..f63d060d 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ spee.ch is a single-serving site that reads and publishes images to and from the * save your connection uri somewhere handy (you will need it when you start the server) * the uri should be in the form `mysql://user:pass@host:port/dbname` * clone this repo - * customize `config/develpment.json` by replacing the value of `Database.PublishUploadPath` with a string representing the local path where you want uploaded files to be stored. + * customize `config/develpment.json` by replacing the value of `Database.DownloadDirectory` with a string representing the local path where you want uploaded files to be stored. * run `npm install` * to start the server, from your command line run `node server.js` while passing three environmental variables: your lbry wallet address (`LBRY_WALLET_ADDRESS`), your mysql connection uri (`MYSQL_CONNECTION_STRING`), and the environment to run (`NODE_ENV`). * i.e. `LBRY_WALLET_ADDRESS= MYSQL_CONNECTION_STRING= NODE_ENV=development node server.js` diff --git a/config/default.json b/config/default.json index a50953a0..1149f468 100644 --- a/config/default.json +++ b/config/default.json @@ -9,10 +9,9 @@ }, "Database": { "MySqlConnectionUri": "none", - "PublishUploadPath": "none" + "DownloadDirectory": "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..44631dd2 100644 --- a/config/development.json +++ b/config/development.json @@ -9,10 +9,9 @@ }, "Database": { "MySqlConnectionUri": "none", - "PublishUploadPath": "C:\\lbry\\speech\\hosted_content\\" + "DownloadDirectory": "/home/ubuntu/Downloads/" }, "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..9dc93f55 100644 --- a/config/production.json +++ b/config/production.json @@ -9,10 +9,9 @@ }, "Database": { "MySqlConnectionUri": "none", - "PublishUploadPath": "/home/lbry/Downloads/" + "DownloadDirectory": "/home/lbry/Downloads/" }, "Logging": { - "LogLevel": "verbose", - "LogDirectory": "/home/lbry/Logs" + "LogLevel": "verbose" } } diff --git a/config/test.json b/config/test.json index bab71bfa..d53960e1 100644 --- a/config/test.json +++ b/config/test.json @@ -9,10 +9,9 @@ }, "Database": { "MySqlConnectionUri": "none", - "PublishUploadPath": "/home/ubuntu/Downloads/" + "DownloadDirectory": "/home/ubuntu/Downloads/" }, "Logging": { - "LogLevel": "debug", - "LogDirectory": "/home/ubuntu/Logs" + "LogLevel": "debug" } } diff --git a/controllers/serveController.js b/controllers/serveController.js index b3dfb700..845dfb57 100644 --- a/controllers/serveController.js +++ b/controllers/serveController.js @@ -98,6 +98,8 @@ function getClaimAndHandleResponse (uri, address, height, resolve, reject) { }); // resolve the request resolve({ + name, + claimId : claim_id, fileName: file_name, filePath: download_path, fileType: mime_type, diff --git a/controllers/statsController.js b/controllers/statsController.js index 327636da..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, 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')) { @@ -20,6 +20,11 @@ module.exports = { action, url, ipAddress, + name, + claimId, + fileName, + fileType, + nsfw, result, }) .then() @@ -58,20 +63,27 @@ module.exports = { } }); }, - getStatsSummary () { - logger.debug('retrieving site statistics'); + getStatsSummary (startDate) { + logger.debug('retrieving statistics'); const deferred = new Promise((resolve, reject) => { // get the raw statistics data db.Stats - .findAll() + .findAll({ + where: { + createdAt: { + gt: startDate, + }, + }, + }) .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; @@ -114,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 }); }) @@ -125,4 +137,68 @@ module.exports = { }); return deferred; }, + getTrendingClaims (startDate) { + logger.debug('retrieving trending statistics'); + const deferred = new Promise((resolve, reject) => { + // get the raw statistics data + db.Stats + .findAll({ + where: { + createdAt: { + gt: startDate, + }, + name: { + not: null, + }, + claimId: { + not: null, + }, + }, + }) + .then(data => { + 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}`; + if (resultHashTable[key] === undefined) { + resultHashTable[key] = { + count : 0, + details: { + name : data[i].name, + claimId : data[i].claimId, + fileName: data[i].fileName, + fileType: data[i].fileType, + nsfw : data[i].nsfw, + }, + }; + } else { + resultHashTable[key]['count'] += 1; + } + } + for (let objKey in resultHashTable) { + if (resultHashTable.hasOwnProperty(objKey)) { + sortableArray.push([ + resultHashTable[objKey]['count'], + resultHashTable[objKey]['details'], + ]); + } + } + sortableArray.sort((a, b) => { + return b[0] - a[0]; + }); + sortedArray = sortableArray.map((a) => { + return a[1]; + }); + // return results + resolve(sortedArray); + }) + .catch(error => { + logger.error('sequelize error', error); + reject(error); + }); + }); + return deferred; + }, }; diff --git a/helpers/libraries/errorHandlers.js b/helpers/libraries/errorHandlers.js index b7ea5a37..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, 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, '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, error); + postToStats(action, originalUrl, ip, null, null, null, null, null, error); res.status(400).send(error.message); } else { - postToStats(action, originalUrl, ip, 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 931623fe..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,7 +13,26 @@ module.exports = (sequelize, { STRING, TEXT }) => { ipAddress: { type : STRING, allowNull: true, - default : null, + }, + name: { + type : STRING, + allowNull: true, + }, + claimId: { + type : STRING, + allowNull: true, + }, + 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 67c82d95..7c80c058 100644 --- a/routes/api-routes.js +++ b/routes/api-routes.js @@ -8,11 +8,11 @@ const errorHandlers = require('../helpers/libraries/errorHandlers.js'); const { postToStats, sendGoogleAnalytics } = require('../controllers/statsController.js'); const config = require('config'); -const hostedContentPath = config.get('Database.PublishUploadPath'); +const hostedContentPath = config.get('Database.DownloadDirectory'); module.exports = app => { - // route to run a claim_list request on the daemon - app.get('/api/streamFile/:name', ({ params, headers }, res) => { + // route to return a file directly + app.get('/api/streamFile/:name', ({ params }, res) => { const filePath = `${hostedContentPath}${params.name}`; res.status(200).sendFile(filePath); }); @@ -24,7 +24,7 @@ module.exports = app => { lbryApi .getClaimsList(params.name) .then(claimsList => { - postToStats('serve', originalUrl, ip, '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, '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, 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, '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 81fd3219..ffe5ec78 100644 --- a/routes/home-routes.js +++ b/routes/home-routes.js @@ -11,7 +11,7 @@ module.exports = app => { app.use('*', ({ originalUrl, ip }, res) => { logger.error(`404 on ${originalUrl}`); // post to stats - postToStats('show', originalUrl, ip, '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 8df97494..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, '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, 'success'); + postToStats('serve', originalUrl, ip, fileInfo.name, fileInfo.claimId, fileInfo.fileName, fileInfo.fileType, fileInfo.nsfw, 'success'); serveFile(fileInfo, res); } } else { - postToStats('serve', originalUrl, ip, '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, '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, 'success'); + postToStats('serve', originalUrl, ip, fileInfo.name, fileInfo.claimId, fileInfo.fileName, fileInfo.fileType, fileInfo.nsfw, 'success'); serveFile(fileInfo, res); } } else { - postToStats('serve', originalUrl, ip, '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 d662d6c9..8f69270a 100644 --- a/routes/show-routes.js +++ b/routes/show-routes.js @@ -1,6 +1,6 @@ const errorHandlers = require('../helpers/libraries/errorHandlers.js'); const { getClaimByClaimId, getClaimByName, getAllClaims } = require('../controllers/serveController.js'); -const { getStatsSummary, postToStats } = require('../controllers/statsController.js'); +const { postToStats, getStatsSummary, getTrendingClaims } = require('../controllers/statsController.js'); module.exports = (app) => { // route to show 'about' page for spee.ch @@ -8,30 +8,44 @@ module.exports = (app) => { // get and render the content res.status(200).render('about'); }); - // route to show the meme-fodder meme maker - app.get('/meme-fodder/play', ({ ip, originalUrl }, res) => { - // get and render the content - getAllClaims('meme-fodder') - .then(orderedFreePublicClaims => { - postToStats('show', originalUrl, ip, 'success'); - res.status(200).render('memeFodder', { claims: orderedFreePublicClaims }); + // route to display a list of the trending images + app.get('/trending', ({ params, headers }, res) => { + const startDate = new Date(); + startDate.setDate(startDate.getDate() - 1); + getTrendingClaims(startDate) + .then(result => { + res.status(200).render('trending', { trendingAssets: result }); }) .catch(error => { - errorHandlers.handleRequestError('show', originalUrl, ip, error, res); + errorHandlers.handleRequestError(error, res); }); }); // route to show statistics for spee.ch app.get('/stats', ({ ip, originalUrl }, res) => { // get and render the content - getStatsSummary() + const startDate = new Date(); + startDate.setDate(startDate.getDate() - 1); + getStatsSummary(startDate) .then(result => { - postToStats('show', originalUrl, ip, 'success'); + postToStats('show', originalUrl, ip, null, null, null, null, null, 'success'); res.status(200).render('statistics', result); }) .catch(error => { errorHandlers.handleRequestError(error, res); }); }); + // route to show the meme-fodder meme maker + app.get('/meme-fodder/play', ({ ip, originalUrl }, res) => { + // get and render the content + getAllClaims('meme-fodder') + .then(orderedFreePublicClaims => { + postToStats('show', originalUrl, ip, null, null, null, null, null, 'success'); + res.status(200).render('memeFodder', { claims: orderedFreePublicClaims }); + }) + .catch(error => { + errorHandlers.handleRequestError('show', originalUrl, ip, error, res); + }); + }); // route to display all free public claims at a given name app.get('/:name/all', ({ ip, originalUrl, params }, res) => { // get and render the content @@ -41,7 +55,7 @@ module.exports = (app) => { res.status(307).render('noClaims'); return; } - postToStats('show', originalUrl, ip, 'success'); + postToStats('show', originalUrl, ip, null, null, null, null, null, 'success'); res.status(200).render('allClaims', { claims: orderedFreePublicClaims }); }) .catch(error => { @@ -59,7 +73,7 @@ module.exports = (app) => { return; } // serve the file or the show route - postToStats('show', originalUrl, ip, 'success'); + postToStats('show', originalUrl, ip, fileInfo.name, fileInfo.claimId, fileInfo.fileName, fileInfo.fileType, fileInfo.nsfw, 'success'); res.status(200).render('show', { fileInfo }); }) .catch(error => { @@ -77,7 +91,7 @@ module.exports = (app) => { return; } // serve the show route - postToStats('show', originalUrl, ip, '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 0a17e56f..614a709d 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, error); + postToStats('publish', '/', null, 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, 'success'); + postToStats('publish', '/', null, null, null, null, null, 'success'); socket.emit('publish-complete', { name: publishParams.name, result }); }) .catch(error => { error = errorHandlers.handlePublishError(error); - postToStats('publish', '/', null, error); + postToStats('publish', '/', null, 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, 'File uploaded, but with errors'); + postToStats('publish', '/', null, 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..48ed5079 100644 --- a/server.js +++ b/server.js @@ -7,12 +7,11 @@ const Handlebars = require('handlebars'); const config = require('config'); const winston = require('winston'); -const hostedContentPath = config.get('Database.PublishUploadPath'); +const hostedContentPath = config.get('Database.DownloadDirectory'); // 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/about.handlebars b/views/about.handlebars index 5c93d61a..9600c2f0 100644 --- a/views/about.handlebars +++ b/views/about.handlebars @@ -14,3 +14,4 @@ {{> footer}} + \ No newline at end of file diff --git a/views/index.handlebars b/views/index.handlebars index a698756f..e3b87ed4 100644 --- a/views/index.handlebars +++ b/views/index.handlebars @@ -4,10 +4,12 @@ {{> publish}} {{> learnMore}} + {{> 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'}}
- - \ No newline at end of file +
\ No newline at end of file diff --git a/views/partials/memeFodderResults.handlebars b/views/partials/memeFodderResults.handlebars index 13ba3922..c47d89f8 100644 --- a/views/partials/memeFodderResults.handlebars +++ b/views/partials/memeFodderResults.handlebars @@ -5,7 +5,7 @@
{{#each claims}} - + {{/each}}
\ No newline at end of file diff --git a/views/partials/trendingAssets.handlebars b/views/partials/trendingAssets.handlebars new file mode 100644 index 00000000..0f94924b --- /dev/null +++ b/views/partials/trendingAssets.handlebars @@ -0,0 +1,19 @@ +
+

Trending

+ {{#each trendingAssets}} + {{#if this.nsfw}} + {{else }} + {{#ifConditional this.fileType '===' 'video/mp4'}} + + {{else}} + + + + {{/ifConditional}} + {{/if}} + {{/each}} +
\ No newline at end of file diff --git a/views/show.handlebars b/views/show.handlebars index fe8935dc..4701240b 100644 --- a/views/show.handlebars +++ b/views/show.handlebars @@ -7,4 +7,17 @@ {{> assetInfo}} {{> footer}} - \ No newline at end of file + + + \ No newline at end of file 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'}}