From 0b032051164cbf49f230dff9183abb48d4a97503 Mon Sep 17 00:00:00 2001 From: Igor Date: Sat, 24 Oct 2020 22:46:37 +0200 Subject: [PATCH 1/8] Added admin page with ref links. Added progress bar on videos longer then 15 minutes --- controllers/frontend/account.js | 22 +++++++- controllers/frontend/mediaBrowsing.js | 75 ++++++++++++++++++++++---- views/admin/adminOverview.pug | 27 +++++++++- views/layout.pug | 1 + views/media.pug | 55 ++++++++++++++----- views/mediaBrowsing/popularUploads.pug | 2 +- views/nodeTubeCss.pug | 8 ++- views/viewPartials/uploadThumbnail.pug | 17 +++++- 8 files changed, 178 insertions(+), 29 deletions(-) diff --git a/controllers/frontend/account.js b/controllers/frontend/account.js index 68bbfc7b..897de8d3 100644 --- a/controllers/frontend/account.js +++ b/controllers/frontend/account.js @@ -14,7 +14,7 @@ const SocialPost = require('../../models/index').SocialPost; const Subscription = require('../../models/index').Subscription; const PushSubscription = require('../../models/index').PushSubscription; const EmailSubscription = require('../../models/index').EmailSubscription; - +const LastWatchedTime = require('../../models/index').LastWatchedTime; const PushEndpoint = require('../../models/index').PushEndpoint; const RSS = require('rss'); @@ -503,6 +503,26 @@ exports.getChannel = async(req, res) => { user.totalViews = totalViews; + for(const upload in uploads){ + console.log(uploads[upload].durationInSeconds) + let lastWatchedTime; + if(uploads[upload].durationInSeconds >= 900){ + console.log("This watch") + console.log(uploads[upload]._id) + console.log(user._id) + lastWatchedTime = await LastWatchedTime.findOne({ + user : req.user._id, + upload: uploads[upload]._id + }); + } + if(lastWatchedTime !== undefined && lastWatchedTime !== null){ + uploads[upload].lastWatchedTime = lastWatchedTime.secondsWatched + console.log(lastWatchedTime.secondsWatched) + } + } + + + user.uploads = uploads; // for(const upload of uploads){ diff --git a/controllers/frontend/mediaBrowsing.js b/controllers/frontend/mediaBrowsing.js index c86b28f9..c658106d 100644 --- a/controllers/frontend/mediaBrowsing.js +++ b/controllers/frontend/mediaBrowsing.js @@ -7,12 +7,12 @@ const User = require('../../models/index').User; const Upload = require('../../models/index').Upload; const SearchQuery = require('../../models/index').SearchQuery; const View = require('../../models/index').View; - +const LastWatchedTime = require('../../models/index').LastWatchedTime; const uploadHelpers = require('../../lib/helpers/settings'); const uploadServer = uploadHelpers.uploadServer; const getFromCache = require('../../caching/getFromCache'); const uploadFilters = require('../../lib/mediaBrowsing/helpers'); - +const timeHelper = require('../../lib/helpers/time'); const { getUploadDuration } = require('../../lib/mediaBrowsing/helpers'); const getSensitivityFilter = uploadFilters.getSensitivityFilter; @@ -40,17 +40,38 @@ if(!process.env.FILE_HOST || process.env.FILE_HOST == 'false'){ const pageLimit = 42; +async function addLastTimeWatched(upload, user){ + console.log("AddLastWatchedTime") + console.log(upload.durationInSeconds) + let lastWatchedTime; + if(upload.durationInSeconds >= 900){ + console.log("This watch") + console.log(upload._id) + console.log(user._id) + lastWatchedTime = await LastWatchedTime.findOne({ + user : user._id, + upload: upload._id + }); + } + if(lastWatchedTime !== undefined && lastWatchedTime !== null){ + // uploads[upload].lastWatchedTime = lastWatchedTime.secondsWatched + console.log(lastWatchedTime.secondsWatched) + return lastWatchedTime.secondsWatched + } + +} + // TODO: pull this function out async function addValuesIfNecessary(upload, channelUrl){ if(upload.fileType == 'video' || upload.fileType == 'audio'){ - if(!upload.durationInSeconds || !upload.formattedDuration){ + if(true){ var server = uploadServer; if(server.charAt(0) == '/') // the slash confuses the file reading, because host root directory is not the same as machine root directory server = server.substr(1); const uploadLocation = `${server}/${channelUrl}/${upload.uniqueTag + upload.fileExtension}`; - + try { const duration = await getUploadDuration(uploadLocation, upload.fileType); // console.log(duration); @@ -59,13 +80,13 @@ async function addValuesIfNecessary(upload, channelUrl){ uploadDocument.durationInSeconds = Math.round(duration.seconds); uploadDocument.formattedDuration = duration.formattedTime; - + const value = Math.round(duration.seconds); const saveDocument = await uploadDocument.save(); - // console.log(saveDocument); - + // console.log("saveDocument") + return value; } catch(err){ /** if the file has been deleted then it won't blow up **/ - // console.log(err); + console.log(err); } // console.log('have to add'); @@ -134,6 +155,14 @@ exports.recentUploads = async(req, res) => { // console.log('rendering'); + if(uploads && uploads.length){ + for(const upload in uploads){ + // console.log(uploads[upload]); + uploads[upload].durationInSeconds = await addValuesIfNecessary(uploads[upload], uploads[upload].uploader && uploads[upload].uploader.channelUrl); + uploads[upload].lastWatchedTime = await addLastTimeWatched(uploads[upload], req.user) + } + } + res.render('mediaBrowsing/recentUploads', { title: 'Recent Uploads', uploads, @@ -316,10 +345,28 @@ exports.popularUploads = async(req, res) => { if(uploads && uploads.length){ for(const upload in uploads){ - // console.log(upload); - addValuesIfNecessary(upload, upload.uploader && upload.uploader.channelUrl); + // console.log(uploads[upload]); + uploads[upload].durationInSeconds = await addValuesIfNecessary(uploads[upload], uploads[upload].uploader && uploads[upload].uploader.channelUrl); + uploads[upload].lastWatchedTime = await addLastTimeWatched(uploads[upload], req.user) } } + // console.log(uploads) + // for(const upload in uploads){ + // // console.log(uploads[upload]._id) + // let lastWatchedTime; + // if(uploads[upload].lastWatchedTime === undefined){ + // lastWatchedTime = await LastWatchedTime.findOne({ + // user : req.user._id, + // upload: uploads[upload]._id + // }); + // } + // if(lastWatchedTime !== null){ + // uploads[upload].lastWatchedTime = lastWatchedTime.secondsWatched + // // console.log(lastWatchedTime.secondsWatched) + // } + // // console.log(uploads[upload].durationInSeconds); + // } + res.render('mediaBrowsing/popularUploads', { title: 'Popular Uploads', @@ -524,6 +571,14 @@ exports.search = async(req, res) => { // error } + if(uploads && uploads.length){ + for(const upload in uploads){ + // console.log(uploads[upload]); + uploads[upload].durationInSeconds = await addValuesIfNecessary(uploads[upload], uploads[upload].uploader && uploads[upload].uploader.channelUrl); + uploads[upload].lastWatchedTime = await addLastTimeWatched(uploads[upload], req.user) + } + } + const siteVisitor = req.siteVisitor; const media = mediaType || 'all'; diff --git a/views/admin/adminOverview.pug b/views/admin/adminOverview.pug index 22aafe2c..1ce8f416 100644 --- a/views/admin/adminOverview.pug +++ b/views/admin/adminOverview.pug @@ -2,8 +2,33 @@ extends ../layout block content div - div + div.col-sm-3 h2 a(href="/admin/users") Users h2 a(href="/admin/subscriptions") Subscriptions + h2 + a(href="/admin/comments") Comments + h2 + a(href="/admin/uploads") Uploads + h2 + a(href="/admin/dailyStats") Daily stats + h2 + a(href="/admin/reacts") Reacts + h2 + a(href="/admin/siteVisitors") Site Visitors + h2 + a(href="/admin/notifications") Notifications + h2 + a(href="/admin/adminAudit") Admin audit + h2 + a(href="/admin/createSocialPost") Create Social Post + h2 + a(href="/admin/oneOffSocialPost") One off social post + h2 + a(href="/pending") Pending requests + h2 + a(href="/support/emails") Support emails + h2 + a(href="/support/reports") Support reports + diff --git a/views/layout.pug b/views/layout.pug index 29104bd4..e9e4189f 100644 --- a/views/layout.pug +++ b/views/layout.pug @@ -32,6 +32,7 @@ html link(rel='manifest', href='/manifest.json') link(rel='alternate', type='application/rss+xml', href='/media/recent/rss') link(href='https://gitcdn.github.io/bootstrap-toggle/2.2.2/css/bootstrap-toggle.min.css', rel='stylesheet') + link(href='https://cdn.plyr.io/3.6.2/plyr.css', rel='stylesheet') block extra_css script(src='/js/lib/jquery-3.1.1.min.js') diff --git a/views/media.pug b/views/media.pug index c84f4739..88c15715 100644 --- a/views/media.pug +++ b/views/media.pug @@ -1,7 +1,7 @@ extends layout -block content +block content if !upload.description style. @media (min-width: 900px) { @@ -399,11 +399,36 @@ block content if upload.fileType === 'video' && upload.status !== 'processing' div.display-div.magnetic(style="min-width:50%;min-height:50%;margin:0 auto;margin-top: -25px;") // margin-top:46px; - - video#media_player.display-element(playsinline poster=`${uploadServer}/${upload.uploader.channelUrl}/${upload.thumbnails.generated || upload.thumbnails.medium}` controls='', style="max-width:100%;background-color:black;") + + //- video#my_video_1.video-js.vjs-default-skin(controls='' data-setup='{}') + //- source(src=`${serverToUse}/${upload.uploader.channelUrl}/${upload.uniqueTag}.mp4`, type='video/mp4') + + //- script. + //- videojs.autoSetup(); + + //- videojs('my_video_1).ready(function(){ + //- console.log(this.options()); + + + //- var myPlayer = this, id = myPlayer.id(); + + //- var aspectRatio = 264/640; + + //- function resizeVideoJS(){ + //- var width = document.getElementById(id).parentElement.offsetWidth; + //- myPlayer.width(width).height( width * aspectRatio ); + + //- } + + + //- resizeVideoJS(); + + //- window.onresize = resizeVideoJS; + //- }); + video#media_player.display-element(playsinline autoplayposter=`${uploadServer}/${upload.uploader.channelUrl}/${upload.thumbnails.generated || upload.thumbnails.medium}` controls='', style="max-width:100%;background-color:black;") // to source.video-source(src=`${serverToUse}/${upload.uploader.channelUrl}/${upload.uniqueTag}.mp4`, type='video/mp4') - + // TODO: load captions programatically if upload.webVTTPath track(kind='captions', label='English captions', src=`${uploadServer}/${upload.uploader.channelUrl}/${upload.webVTTPath}`, srclang='en', default='') @@ -489,11 +514,11 @@ block content // TODO: show this if it's pending or not - if upload.visibility != 'pending' - if alreadySubbed - button.subscribe.btn.fw.btn-danger.op80.unsubscribeButton(style="border-radius:4px;") Unsubscribe (#{subscriberAmount}) - else - button.subscribe.btn.fw.btn-success.op80.subscribeButton(style="border-radius:4px;") Subscribe (#{subscriberAmount}) + + if alreadySubbed + button.subscribe.btn.fw.btn-danger.op80.unsubscribeButton(style="border-radius:4px;") Unsubscribe (#{subscriberAmount}) + else + button.subscribe.btn.fw.btn-success.op80.subscribeButton(style="border-radius:4px;") Subscribe (#{subscriberAmount}) if user div(style="margin-top:12px") @@ -670,7 +695,12 @@ block content if ( upload.durationInSeconds > (15 * 60) ) && user if lastWatchedTime - p.fw.fileSizeText(style="margin-top:15px;color:a5a5a5;") Last Watched Time: #{formattedLastWatchedTime} + p.fw.fileSizeText(style="margin-top:15px;color:a5a5a5;") Las Watched Time: #{formattedLastWatchedTime} + script. + document.getElementById('media_player').addEventListener('loadedmetadata', function() { + this.currentTime = lastWatchedTime; + }, false); + //- document.getElementById('media_player').src = '' + serverToUse + '/' + upload.uploader.channelUrl + '/' upload.uniqueTag + '.mp4#t=00:00:' + lastWatchedTime else p.fw.fileSizeText(style="margin-top:15px;color:a5a5a5;") No Last Watched Time @@ -859,7 +889,7 @@ block extra_js if user script. - + $(document).ready(function(){ var alreadyHaveEmailNotifsOn = '#{alreadySubscribedForEmails}' == 'true' @@ -1015,9 +1045,10 @@ block extra_js // when show less button is clicked showLessButton.click(function () { uploadDescriptionText.height('194'); - + showMoreButton.show() showLessButton.hide() + document.getElementsByTagName('h2')[2].scrollIntoView(); }) diff --git a/views/mediaBrowsing/popularUploads.pug b/views/mediaBrowsing/popularUploads.pug index f1332f46..589ba02c 100644 --- a/views/mediaBrowsing/popularUploads.pug +++ b/views/mediaBrowsing/popularUploads.pug @@ -54,7 +54,7 @@ block content each upload in uploads div.col-xs-12.col-sm-6.col-md-6.col-lg-4(style="text-align:center;height:340px;margin-bottom:34px;") - + include ../viewPartials/uploadThumbnail include ../viewPartials/uploadDetails diff --git a/views/nodeTubeCss.pug b/views/nodeTubeCss.pug index 7a235807..fd336043 100644 --- a/views/nodeTubeCss.pug +++ b/views/nodeTubeCss.pug @@ -144,6 +144,9 @@ style. margin: 0 auto; border-radius: 5px; } + .plyr--full-ui input[type="range"] { + color: red; + } .plyr.plyr__video-wrapper { background: white; @@ -162,7 +165,7 @@ style. max-width: 405px; height: 210px; max-height: 210px; - border-radius: 7px; + max-width:100%; /*border:1px solid white;*/ } @@ -291,6 +294,7 @@ style. } .image-container { + height: 220px; display:inline-block; border:1px solid #5b5a5a; margin:0 auto; @@ -304,7 +308,7 @@ style. /*transform: scale(1.05) translate(0px, 30px);*/ - transform: scale(1.12); + transform: scale(1.05); -webkit-filter: brightness(120%); } diff --git a/views/viewPartials/uploadThumbnail.pug b/views/viewPartials/uploadThumbnail.pug index 349c5f2f..7c57bb04 100644 --- a/views/viewPartials/uploadThumbnail.pug +++ b/views/viewPartials/uploadThumbnail.pug @@ -1,3 +1,11 @@ +style. + progress { + width: 100%; + border: 0px solid red; + background: LightGray; + height: 10px; + } + progress::-moz-progress-bar { background: red; } div.holder(style="border:") a.title-anchor(href=`/user/${upload.uploader.channelUrl || channelUrl}/${upload.uniqueTag}` style="color:#7d7373;" ) div.image-container(style="") @@ -5,8 +13,12 @@ div.holder(style="border:") img.upload-thumbnail.preview-image(src=`${uploadServer}/${channelUrl || upload.uploader.channelUrl}/${upload.thumbnails.custom}` style="") else if upload.fileType == 'video' && upload.thumbnails && upload.thumbnails.generated - img.upload-thumbnail.preview-image(src=`${uploadServer}/${channelUrl || upload.uploader.channelUrl}/${upload.thumbnails.generated}` style="") - + + if !upload.lastWatchedTime + img.upload-thumbnail.preview-image(src=`${uploadServer}/${channelUrl || upload.uploader.channelUrl}/${upload.thumbnails.generated}` style="margin-bottom: -1.5%; height: 220px; max-height: 220px") + else + img.upload-thumbnail.preview-image(src=`${uploadServer}/${channelUrl || upload.uploader.channelUrl}/${upload.thumbnails.generated}` style="margin-bottom: -1.5%") + progress(value=upload.lastWatchedTime max=upload.durationInSeconds) else if upload.fileType == 'video' && upload.thumbnails && upload.thumbnails.medium img.upload-thumbnail.preview-image(src=`${uploadServer}/${channelUrl || upload.uploader.channelUrl}/${upload.thumbnails.medium}` style="") @@ -23,3 +35,4 @@ div.holder(style="border:") else if upload.fileType == 'unknown' img.upload-thumbnail.preview-image(src='/images/no_img.png') + From cf159de2fda35b1d10bb52a4638b8fa00d74c2be Mon Sep 17 00:00:00 2001 From: Igor Date: Sat, 24 Oct 2020 23:00:50 +0200 Subject: [PATCH 2/8] small fix --- views/viewPartials/uploadThumbnail.pug | 1 + 1 file changed, 1 insertion(+) diff --git a/views/viewPartials/uploadThumbnail.pug b/views/viewPartials/uploadThumbnail.pug index 7c57bb04..62dbff1a 100644 --- a/views/viewPartials/uploadThumbnail.pug +++ b/views/viewPartials/uploadThumbnail.pug @@ -6,6 +6,7 @@ style. height: 10px; } progress::-moz-progress-bar { background: red; } + progress::-webkit-progress-value { background: red; } div.holder(style="border:") a.title-anchor(href=`/user/${upload.uploader.channelUrl || channelUrl}/${upload.uniqueTag}` style="color:#7d7373;" ) div.image-container(style="") From e9ebe299adb3a42cb5d8121cc0a3456448ba8d83 Mon Sep 17 00:00:00 2001 From: Anthony Date: Sat, 24 Oct 2020 20:21:35 -0600 Subject: [PATCH 3/8] using zoho with noreply --- config/nodemailer.js | 8 +++---- config/protonmailTransport.js | 40 +++++++++++++++++----------------- controllers/backend/account.js | 27 +++++++++++------------ 3 files changed, 37 insertions(+), 38 deletions(-) diff --git a/config/nodemailer.js b/config/nodemailer.js index e63cf75b..6686eff3 100644 --- a/config/nodemailer.js +++ b/config/nodemailer.js @@ -4,12 +4,12 @@ var mg = require('nodemailer-mailgun-transport'); process.on('unhandledRejection', console.log); const zohoTransport = nodemailer.createTransport({ - host: process.env.EMAIL_SMTP_HOST, - port: process.env.EMAIL_SMTP_PORT, + host: process.env.NODETUBE_NOREPLY_EMAIL_HOST, + port: process.env.NODETUBE_NOREPLY_EMAIL_PORT, secure: true, // use SSL auth: { - user: process.env.EMAIL_ADDRESS, - pass: process.env.NODETUBE_VERIFY_EMAIL_PASSWORD + user: process.env.NODETUBE_NOREPLY_EMAIL_ADDRESS, + pass: process.env.NODETUBE_NOREPLY_EMAIL_PASSWORD } }); diff --git a/config/protonmailTransport.js b/config/protonmailTransport.js index cb4aae5e..3bd08b6e 100644 --- a/config/protonmailTransport.js +++ b/config/protonmailTransport.js @@ -1,20 +1,20 @@ -const pm = require('protonmail-api'); - -let protonMailTransport; -(async function(){ - protonMailTransport = await pm.connect({ - username: process.env.PROTONMAIL_USERNAME, - password: process.env.PROTONMAIL_PASSWORD - }); - - console.log('Protonmail setup'); -})() - -async function sendProtonMail(mailOptions){ - const response = await protonMailTransport.sendEmail(mailOptions); - return response; -} - -module.exports = { - sendProtonMail -}; +// const pm = require('protonmail-api'); +// +// let protonMailTransport; +// (async function(){ +// protonMailTransport = await pm.connect({ +// username: process.env.PROTONMAIL_USERNAME, +// password: process.env.PROTONMAIL_PASSWORD +// }); +// +// console.log('Protonmail setup'); +// })() +// +// async function sendProtonMail(mailOptions){ +// const response = await protonMailTransport.sendEmail(mailOptions); +// return response; +// } +// +// module.exports = { +// sendProtonMail +// }; diff --git a/controllers/backend/account.js b/controllers/backend/account.js index 765ca4a6..3a159efb 100644 --- a/controllers/backend/account.js +++ b/controllers/backend/account.js @@ -17,7 +17,7 @@ const mkdirp = Promise.promisifyAll(require('mkdirp')); const randomstring = require('randomstring'); const mailTransports = require('../../config/nodemailer'); -const {sendProtonMail} = require('../../config/protonmailTransport'); +// const {sendProtonMail} = require('../../config/protonmailTransport'); const importerDownloadFunction = require('../../lib/uploading/importer'); @@ -27,6 +27,8 @@ const importerDownloadFunction = require('../../lib/uploading/importer'); // console.log(importerDownloadFunction); const mailgunTransport = mailTransports.mailgunTransport; +const zohoTransport = mailTransports.zohoTransport; + const User = require('../../models/index').User; const getMediaType = require('../../lib/uploading/media'); @@ -359,12 +361,12 @@ exports.postReset = async(req, res, next) => { const mailOptions = { to: user.email, - from: process.env.FORGOT_PASSWORD_EMAIL_ADDRESS, + from: process.env.NODETUBE_NOREPLY_EMAIL_ADDRESS, subject: `Your ${brandName} password has been reset`, text: `Hello,\n\nThis is a confirmation that the password for your account ${user.email} has just been changed.\n` }; - const response = await mailgunTransport.sendMail(mailOptions); + const response = await zohoTransport.sendMail(mailOptions); // console.log(response); @@ -404,7 +406,7 @@ exports.postForgot = async(req, res, next) => { const mailOptions = { to: user.email, - from: process.env.FORGOT_PASSWORD_EMAIL_ADDRESS, + from: process.env.NODETUBE_NOREPLY_EMAIL_ADDRESS, subject: `Reset your password on ${brandName}`, text: `You are receiving this email because you (or someone else) have requested the reset of the password for your account.\n\n Please click on the following link, or paste this into your browser to complete the process:\n\n @@ -412,7 +414,7 @@ exports.postForgot = async(req, res, next) => { If you did not request this, please ignore this email and your password will remain unchanged.\n` }; - const response = await mailgunTransport.sendMail(mailOptions); + const response = await zohoTransport.sendMail(mailOptions); // console.log(response); @@ -457,18 +459,15 @@ exports.postConfirmEmail = async(req, res, next) => { const mailOptions = { to: user.email, + from: process.env.NODETUBE_NOREPLY_EMAIL_ADDRESS, subject: `Confirm your email on ${brandName}`, - body: `You are receiving this email because you (or someone else) has attempted to link this email to their account. -

- Please click on the following link, or paste this into your browser to complete the process: -

- http://${req.headers.host}/confirmEmail/${token} -

- If you did not request this, please ignore this email and no further steps will be needed. -
` + text: `You are receiving this email because you (or someone else) has attempted to link this email to their account.\n\n + Please click on the following link, or paste this into your browser to complete the process:\n\n + http://${req.headers.host}/confirmEmail/${token}\n\n + If you did not request this, please ignore this email and no further steps will be needed.\n` }; - const response = await sendProtonMail(mailOptions) + const response = await zohoTransport.sendMail(mailOptions); // console.log(response); From f9e16ba7e67823ba72d73d482dbf754c8e3fc37c Mon Sep 17 00:00:00 2001 From: Anthony Date: Sat, 24 Oct 2020 20:38:31 -0600 Subject: [PATCH 4/8] turn on forgotten page --- controllers/backend/account.js | 1 + views/account/login.pug | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/controllers/backend/account.js b/controllers/backend/account.js index 3a159efb..0bf85211 100644 --- a/controllers/backend/account.js +++ b/controllers/backend/account.js @@ -366,6 +366,7 @@ exports.postReset = async(req, res, next) => { text: `Hello,\n\nThis is a confirmation that the password for your account ${user.email} has just been changed.\n` }; + // turn an email noting that is ___ const response = await zohoTransport.sendMail(mailOptions); // console.log(response); diff --git a/views/account/login.pug b/views/account/login.pug index 6178350f..7b3ab595 100644 --- a/views/account/login.pug +++ b/views/account/login.pug @@ -28,7 +28,10 @@ block content | Login // turn off forgot password, should expose it as an env var - //a.btn.btn-link(href='/forgot') Forgot your password? + + //if forgotPasswordFunctionalityOn + if 1 == 1 + a.btn.btn-link(href='/forgot') Forgot your password? .form-group .col-sm-12 hr From a5b80a5d3c08d6b68a37524ed336fe46249ef9c8 Mon Sep 17 00:00:00 2001 From: Anthony Date: Sat, 24 Oct 2020 21:41:55 -0600 Subject: [PATCH 5/8] about to finish email notifs --- .env.private.sample | 17 +++++++++++++---- controllers/backend/uploading.js | 2 +- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/.env.private.sample b/.env.private.sample index a3d88e8f..27701e25 100644 --- a/.env.private.sample +++ b/.env.private.sample @@ -28,10 +28,19 @@ BACKBLAZE_ACCOUNT_ID= BACKBLAZE_APP_KEY= BACKBLAZE_BUCKET= -# setup for nodemailer to send verification emails -NODETUBE_VERIFY_EMAIL_PASSWORD= -EMAIL_HOST= -EMAIL_ADDRESS= +# setup for nodemailer to send verification emails/reset password emails + +# your email address for no reply (noreply@domainname.com) +NODETUBE_NOREPLY_EMAIL_ADDRESS='' + +# email password for no reply functionality +NODETUBE_NOREPLY_EMAIL_PASSWORD='' + +# host, like smtp.mailprovder.com +NODETUBE_NOREPLY_EMAIL_HOST='' + +# port, like 465 for ssl stmp +NODETUBE_NOREPLY_EMAIL_PORT='' # mailgun integration for sending emails MAILGUN_API_KEY='exampleApiKey14134' diff --git a/controllers/backend/uploading.js b/controllers/backend/uploading.js index 54198b77..1b4958ac 100644 --- a/controllers/backend/uploading.js +++ b/controllers/backend/uploading.js @@ -601,7 +601,7 @@ exports.postFileUpload = async(req, res) => { uploadLogger.info('Update users push notifications', logObject); - // user + // do email notifications for the user updateUsersEmailNotifications(user, upload); uploadLogger.info('Update users email notifications', logObject); From 3dde921180c00232fc3f8382a2ad92e395e08185 Mon Sep 17 00:00:00 2001 From: Anthony Date: Sat, 24 Oct 2020 22:09:42 -0600 Subject: [PATCH 6/8] finish email notifications --- controllers/backend/uploading.js | 2 +- lib/uploading/helpers.js | 31 +++++++++++++++++++++---------- 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/controllers/backend/uploading.js b/controllers/backend/uploading.js index 1b4958ac..8eafbed9 100644 --- a/controllers/backend/uploading.js +++ b/controllers/backend/uploading.js @@ -602,7 +602,7 @@ exports.postFileUpload = async(req, res) => { uploadLogger.info('Update users push notifications', logObject); // do email notifications for the user - updateUsersEmailNotifications(user, upload); + updateUsersEmailNotifications(user, upload, req.host); uploadLogger.info('Update users email notifications', logObject); diff --git a/lib/uploading/helpers.js b/lib/uploading/helpers.js index 4e36d418..61996170 100644 --- a/lib/uploading/helpers.js +++ b/lib/uploading/helpers.js @@ -6,9 +6,10 @@ const PushEndpoint = require('../../models/index').PushEndpoint; const PushSubscription = require('../../models/index').PushSubscription; const EmailSubscription = require('../../models/index').EmailSubscription; -const { protonmailTransport } = require('../../config/protonmailTransport'); +// const { protonmailTransport } = require('../../config/protonmailTransport'); const pushNotificationLib = require('../../lib/mediaPlayer/pushNotification'); -const {sendProtonMail} = require('../../config/protonmailTransport'); +const { zohoTransport } = require('../../config/nodemailer'); + // can't we just pass the upload, why have to hit the db? @@ -179,7 +180,7 @@ async function updateUsersPushNotifications(user, upload){ // } } -async function updateUsersEmailNotifications(user, upload){ +async function updateUsersEmailNotifications(user, upload, host){ // TODO : have to know what the upload's user's thing @@ -226,20 +227,30 @@ async function updateUsersEmailNotifications(user, upload){ const uploadedImage = `/uploads/${user.channelUrl}/${upload.uniqueTag}.jpg`; + // const mailOptions = { + // to: userToFindEmail.email, + // subject: `New upload by: ${user.channelUrl}: ${upload.title}`, + // body: ` + // ${user.channelUrl} has uploaded a new ${upload.fileType}: ${upload.title}. + // + // // TODO: what can we all stick in here? + // Video preview + // ` + // }; + const mailOptions = { to: userToFindEmail.email, + from: process.env.NODETUBE_NOREPLY_EMAIL_ADDRESS, subject: `New upload by: ${user.channelUrl}: ${upload.title}`, - body: ` - ${user.channelUrl} has uploaded a new ${upload.fileType}: ${upload.title}. - - // TODO: what can we all stick in here? - Video preview - ` + text: `${user.channelUrl} has uploaded a new ${upload.fileType}: ${upload.title}:\n\n + Please click on the following link, or paste this into your browser to view the upload:\n\n + http://${host}/user/${user.channelUrl}/${upload.uniqueTag}\n\n + You are receiving this email because you are subscribed to ${user.channelUrl} on NewTube.app\n` }; console.log(mailOptions); - const response = await sendProtonMail(mailOptions) + const response = await zohoTransport.sendMail(mailOptions) console.log(response); From 3245c941dce2f00cff383f322aecae110237e6bc Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 25 Oct 2020 20:29:01 +1100 Subject: [PATCH 7/8] Fix variable scoping bug --- controllers/frontend/account.js | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/controllers/frontend/account.js b/controllers/frontend/account.js index 897de8d3..44ce971f 100644 --- a/controllers/frontend/account.js +++ b/controllers/frontend/account.js @@ -504,25 +504,23 @@ exports.getChannel = async(req, res) => { user.totalViews = totalViews; for(const upload in uploads){ - console.log(uploads[upload].durationInSeconds) + console.log(uploads[upload].durationInSeconds); let lastWatchedTime; if(uploads[upload].durationInSeconds >= 900){ - console.log("This watch") - console.log(uploads[upload]._id) - console.log(user._id) + console.log('This watch'); + console.log(uploads[upload]._id); + console.log(user._id); lastWatchedTime = await LastWatchedTime.findOne({ user : req.user._id, upload: uploads[upload]._id }); } if(lastWatchedTime !== undefined && lastWatchedTime !== null){ - uploads[upload].lastWatchedTime = lastWatchedTime.secondsWatched - console.log(lastWatchedTime.secondsWatched) - } + uploads[upload].lastWatchedTime = lastWatchedTime.secondsWatched; + console.log(lastWatchedTime.secondsWatched); + } } - - user.uploads = uploads; // for(const upload of uploads){ @@ -533,19 +531,23 @@ exports.getChannel = async(req, res) => { const joinedTimeAgo = timeAgoEnglish.format(user.createdAt); - const pushSubscriptionSearchQuery = { - subscribedToUser : user._id, - subscribingUser: req.user._id, - active: true - } - let existingPushSub; if(req.user){ + const pushSubscriptionSearchQuery = { + subscribedToUser : user._id, + subscribingUser: req.user._id, + active: true + }; existingPushSub = await PushSubscription.findOne(pushSubscriptionSearchQuery); } let existingEmailSub; if(req.user){ + const pushSubscriptionSearchQuery = { + subscribedToUser : user._id, + subscribingUser: req.user._id, + active: true + }; existingEmailSub = await EmailSubscription.findOne(pushSubscriptionSearchQuery); } From 1e57b1580c59eabb66539c20e83595293cd746b1 Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 25 Oct 2020 22:13:29 +1100 Subject: [PATCH 8/8] Add swal for when non user clicks email sub --- views/account/channel.pug | 42 +++++++++++++++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 4 deletions(-) diff --git a/views/account/channel.pug b/views/account/channel.pug index 93640184..ea6c5380 100644 --- a/views/account/channel.pug +++ b/views/account/channel.pug @@ -86,9 +86,16 @@ block content if user div(style="margin-top:12px") // TODO: this should create a push subsciption, and it will also send a query to see if it should create a new service worker - h2.share-button.pushNotificationIcon(style="display:inline") + h2.fw.share-button.pushNotificationIcon(style="display:inline") i.share-icon.fas.fa-bell(aria-hidden="true" style="cursor:pointer;font-size:25px;margin-left:0px;color:white;") - h2.share-button.emailNotificationIcon(style="display:inline") + h2.fw.share-button.emailNotificationIcon(style="display:inline") + i.share-icon.fas.fa-envelope(aria-hidden="true" style="cursor:pointer;font-size:25px;margin-left:10px;color:white;") + else + div(style="margin-top:12px") + // TODO: this should create a push subsciption, and it will also send a query to see if it should create a new service worker + h2.fw.share-button.pushNotificationIcon(style="display:inline") + i.share-icon.fas.fa-bell(aria-hidden="true" style="cursor:pointer;font-size:25px;margin-left:0px;color:white;") + h2.fw.share-button.emailNotificationIcon(style="display:inline") i.share-icon.fas.fa-envelope(aria-hidden="true" style="cursor:pointer;font-size:25px;margin-left:10px;color:white;") // todo: else @@ -149,7 +156,7 @@ block content //button.undelete-account.btn.btn-warning Undelete Account And Unban Ip if user.role == 'admin' button.delete-ips.btn.btn-warning Undelete All Accounts / Unban All Ips - + div @@ -259,7 +266,7 @@ block content $(document).ready(function(){ var alreadyHaveEmailNotifsOn = '#{alreadySubscribedForEmails}' == 'true' - + console.log('already have email notis on') if (alreadyHaveEmailNotifsOn) { @@ -434,6 +441,33 @@ block content main(); }) + $('.emailNotificationIcon').click(function () { + // TODO: How to make it so that the user immediately gets email subs after + // signing in. + Swal.mixin({ + title: 'Choose method of email subscription', + showCancelButton: true, + }).queue([ + { + html: '
' + + '

Please sign in to continue.

', + confirmButtonText: 'Subscribe without sign in', + }, + { + title: 'Choose method of email subscription', + confirmButtonText: 'Subscribe', + input: 'email', + inputLabel: 'Get updates without sign in', + inputPlaceholder: 'Enter your email address' + } + ]).then((result) => { + console.log('result', result.value) + if (result.value) { + const email = result.value[1] + } + }) + }) +