diff --git a/templates/account-channels.pug b/templates/account-channels.pug index b1d6aa7b..7b2a1dc8 100644 --- a/templates/account-channels.pug +++ b/templates/account-channels.pug @@ -1,103 +1,88 @@ -doctype html -html(lang="en") - head - include head - +head() - body - #wrap - nav.navbar.navbar-inverse.navbar-fixed-top(role="navigation") - include nav - +navheader() - #nav-collapsible.collapse.navbar-collapse - ul.nav.navbar-nav - +navdefaultlinks() - +navloginlogout() - section#mainpage - .container - if !loggedIn - .col-lg-6.col-lg-offset-3.col-md-6.col-md-offset-3 - .alert.alert-danger.messagebox.center - strong Authorization Required - p You must be logged in to view this page. - else - .col-lg-6.col-md-6 - h3 My Channels - if deleteChannelError - .alert.alert-danger.center.messagebox - strong Channel Deletion Failed - p= deleteChannelError - if channels.length == 0 - .center - strong You haven't registered any channels - else - table.table.table-bordered - thead - tr - th Channel - tbody - for c in channels - tr - th - form.form-inline.pull-right(action="/account/channels", method="post", onsubmit="return confirm('Are you sure you want to delete " +c.name+ "? This cannot be undone');") - input(type="hidden", name="_csrf", value=csrfToken) - input(type="hidden", name="action", value="delete_channel") - input(type="hidden", name="name", value=c.name) - button.btn.btn-xs.btn-danger(type="submit") Delete - span.glyphicon.glyphicon-trash - a(href=`/${channelPath}/${c.name}`, style="margin-left: 5px")= c.name - .col-lg-6.col-md-6 - h3 Register a new channel - if newChannelError - .alert.alert-danger.messagebox.center - strong Channel Registration Failed - p= newChannelError - form(action="/account/channels", method="post") - input(type="hidden", name="_csrf", value=csrfToken) - input(type="hidden", name="action", value="new_channel") - .form-group - label.control-label(for="channelname") Channel URL - .input-group - span.input-group-addon #{baseUrl}/#{channelPath}/ - input#channelname.form-control(type="text", name="name", maxlength="30", onkeyup="checkChannel()") - p#validate_channel.text-danger.pull-right - button#register.btn.btn-primary.btn-block(type="submit") Register +extends layout.pug - include footer - +footer() - script( type='text/javascript'). - function checkChannel(){ - function nameIsInvalid(id){ - if(/\s/.test(id)){ - return 'Channel URL may not contain spaces'; - } - if(id === ''){ - return 'Channel URL must not be empty'; - } - if(!/^[\w-]{1,30}$/.test(id)){ - return 'Channel URL may only consist of a-z, A-Z, 0-9, - and _'; - } - return false; +block content + if !loggedIn + .col-lg-6.col-lg-offset-3.col-md-6.col-md-offset-3 + .alert.alert-danger.messagebox.center + strong Authorization Required + p You must be logged in to view this page. + else + .col-lg-6.col-md-6 + h3 My Channels + if deleteChannelError + .alert.alert-danger.center.messagebox + strong Channel Deletion Failed + p= deleteChannelError + if channels.length == 0 + .center + strong You haven't registered any channels + else + table.table.table-bordered + thead + tr + th Channel + tbody + for c in channels + tr + th + form.form-inline.pull-right(action="/account/channels", method="post", onsubmit="return confirm('Are you sure you want to delete " +c.name+ "? This cannot be undone');") + input(type="hidden", name="_csrf", value=csrfToken) + input(type="hidden", name="action", value="delete_channel") + input(type="hidden", name="name", value=c.name) + button.btn.btn-xs.btn-danger(type="submit") Delete + span.glyphicon.glyphicon-trash + a(href=`/${channelPath}/${c.name}`, style="margin-left: 5px")= c.name + .col-lg-6.col-md-6 + h3 Register a new channel + if newChannelError + .alert.alert-danger.messagebox.center + strong Channel Registration Failed + p= newChannelError + form(action="/account/channels", method="post") + input(type="hidden", name="_csrf", value=csrfToken) + input(type="hidden", name="action", value="new_channel") + .form-group + label.control-label(for="channelname") Channel URL + .input-group + span.input-group-addon #{baseUrl}/#{channelPath}/ + input#channelname.form-control(type="text", name="name", maxlength="30", onkeyup="checkChannel()") + p#validate_channel.text-danger.pull-right + button#register.btn.btn-primary.btn-block(type="submit") Register + +append footer + script(type='text/javascript'). + function checkChannel(){ + function nameIsInvalid(id){ + if(/\s/.test(id)){ + return 'Channel URL may not contain spaces'; } - - var box = $("#channelname"); - var value = box.val(); - var lastkey = Date.now(); - box.data("lastkey", lastkey); - - setTimeout(function () { - if (box.data("lastkey") !== lastkey || box.val() !== value) { - return; - } - if(nameIsInvalid(value)){ - $('#validate_channel').text(nameIsInvalid(value)) - .parent().addClass('has-error').removeClass('has-success'); - $('#register').addClass('disabled'); - } else { - $('#validate_channel').text('') - .parent().addClass('has-success').removeClass('has-error'); - $('#register').removeClass('disabled'); - } - }, 200); - + if(id === ''){ + return 'Channel URL must not be empty'; + } + if(!/^[\w-]{1,30}$/.test(id)){ + return 'Channel URL may only consist of a-z, A-Z, 0-9, - and _'; + } + return false; } + var box = $("#channelname"); + var value = box.val(); + var lastkey = Date.now(); + box.data("lastkey", lastkey); + + setTimeout(function () { + if (box.data("lastkey") !== lastkey || box.val() !== value) { + return; + } + if(nameIsInvalid(value)){ + $('#validate_channel').text(nameIsInvalid(value)) + .parent().addClass('has-error').removeClass('has-success'); + $('#register').addClass('disabled'); + } else { + $('#validate_channel').text('') + .parent().addClass('has-success').removeClass('has-error'); + $('#register').removeClass('disabled'); + } + }, 200); + + } diff --git a/templates/account-edit.pug b/templates/account-edit.pug index bc8881b1..2882cfbd 100644 --- a/templates/account-edit.pug +++ b/templates/account-edit.pug @@ -1,96 +1,83 @@ -doctype html -html(lang="en") - head - include head - +head() - body - #wrap - nav.navbar.navbar-inverse.navbar-fixed-top(role="navigation") - include nav - +navheader() - #nav-collapsible.collapse.navbar-collapse - ul.nav.navbar-nav - +navdefaultlinks() - +navloginlogout() - section#mainpage - .container - if !loggedIn - .col-lg-6.col-lg-offset-3.col-md-6.col-md-offset-3 - .alert.alert-danger.messagebox.center - strong Authorization Required - p You must be logged in to view this page. - else - .col-lg-6.col-lg-offset-3.col-md-6.col-md-offset-3 - if successMessage - .alert.alert-success.center - p= successMessage - else if errorMessage - .alert.alert-danger.center - p= errorMessage - h3 Change Password - form(action="/account/edit", method="post", onsubmit="return validatePasswordChange()") - input(type="hidden", name="_csrf", value=csrfToken) - input(type="hidden", name="action", value="change_password") - .form-group - label.control-label(for="username") Username - input#username.form-control(type="text", name="name", value=loginName, disabled=true) - .form-group - label.control-label(for="oldpassword") Current Password - input#oldpassword.form-control(type="password", name="oldpassword") - .form-group - label.control-label(for="newpassword") New Password - input#newpassword.form-control(type="password", name="newpassword") - .form-group - label.control-label(for="newpassword_confirm") Confirm New Password - input#newpassword_confirm.form-control(type="password", name="newpassword_confirm") - button#changepassbtn.btn.btn-danger.btn-block(type="submit") Change Password - hr - h3 Change Email - form(action="/account/edit", method="post", onsubmit="return submitEmail()") - input(type="hidden", name="_csrf", value=csrfToken) - input(type="hidden", name="action", value="change_email") - .form-group - label.control-label(for="username2") Username - input#username2.form-control(type="text", name="name", value=loginName, disabled=true) - .form-group - label.control-label(for="password2") Password - input#password2.form-control(type="password", name="password") - .form-group - label.control-label(for="email") New Email - input#email.form-control(type="email", name="email") - button#changeemailbtn.btn.btn-danger.btn-block(type="submit") Change Email - include footer - +footer() - script(type="text/javascript"). - function validatePasswordChange() { - var pw = $("#newpassword").val(); - var pwc = $("#newpassword_confirm").val(); - $("#passwordempty").remove(); - $("#passwordmismatch").remove(); +extends layout.pug - if (pw === '') { +block content + if !loggedIn + .col-lg-6.col-lg-offset-3.col-md-6.col-md-offset-3 + .alert.alert-danger.messagebox.center + strong Authorization Required + p You must be logged in to view this page. + else + .col-lg-6.col-lg-offset-3.col-md-6.col-md-offset-3 + if successMessage + .alert.alert-success.center + p= successMessage + else if errorMessage + .alert.alert-danger.center + p= errorMessage + h3 Change Password + form(action="/account/edit", method="post", onsubmit="return validatePasswordChange()") + input(type="hidden", name="_csrf", value=csrfToken) + input(type="hidden", name="action", value="change_password") + .form-group + label.control-label(for="username") Username + input#username.form-control(type="text", name="name", value=loginName, disabled=true) + .form-group + label.control-label(for="oldpassword") Current Password + input#oldpassword.form-control(type="password", name="oldpassword") + .form-group + label.control-label(for="newpassword") New Password + input#newpassword.form-control(type="password", name="newpassword") + .form-group + label.control-label(for="newpassword_confirm") Confirm New Password + input#newpassword_confirm.form-control(type="password", name="newpassword_confirm") + button#changepassbtn.btn.btn-danger.btn-block(type="submit") Change Password + hr + h3 Change Email + form(action="/account/edit", method="post", onsubmit="return submitEmail()") + input(type="hidden", name="_csrf", value=csrfToken) + input(type="hidden", name="action", value="change_email") + .form-group + label.control-label(for="username2") Username + input#username2.form-control(type="text", name="name", value=loginName, disabled=true) + .form-group + label.control-label(for="password2") Password + input#password2.form-control(type="password", name="password") + .form-group + label.control-label(for="email") New Email + input#email.form-control(type="email", name="email") + button#changeemailbtn.btn.btn-danger.btn-block(type="submit") Change Email + +append footer + script(type="text/javascript"). + function validatePasswordChange() { + var pw = $("#newpassword").val(); + var pwc = $("#newpassword_confirm").val(); + $("#passwordempty").remove(); + $("#passwordmismatch").remove(); + + if (pw === '') { + $("#newpassword").parent().addClass("has-error"); + $("
").addClass("text-danger") + .attr("id", "passwordempty") + .text("Password must not be empty") + .insertAfter($("#newpassword")); + return false; + } else { + if (pw !== pwc) { + $("#newpassword_confirm").parent().addClass("has-error"); $("#newpassword").parent().addClass("has-error"); $("").addClass("text-danger") - .attr("id", "passwordempty") - .text("Password must not be empty") - .insertAfter($("#newpassword")); + .attr("id", "passwordmismatch") + .text("Passwords do not match") + .insertAfter($("#newpassword_confirm")); return false; } else { - if (pw !== pwc) { - $("#newpassword_confirm").parent().addClass("has-error"); - $("#newpassword").parent().addClass("has-error"); - $("").addClass("text-danger") - .attr("id", "passwordmismatch") - .text("Passwords do not match") - .insertAfter($("#newpassword_confirm")); - return false; - } else { - $("#username").attr("disabled", false); - return true; - } + $("#username").attr("disabled", false); + return true; } } - function submitEmail() { - $("#username2").attr("disabled", false); - return true; - } + } + function submitEmail() { + $("#username2").attr("disabled", false); + return true; + } diff --git a/templates/account-passwordrecover.pug b/templates/account-passwordrecover.pug index aff5cec9..09e3b119 100644 --- a/templates/account-passwordrecover.pug +++ b/templates/account-passwordrecover.pug @@ -1,28 +1,13 @@ -doctype html -html(lang="en") - head - include head - +head() - body - #wrap - nav.navbar.navbar-inverse.navbar-fixed-top(role="navigation") - include nav - +navheader() - #nav-collapsible.collapse.navbar-collapse - ul.nav.navbar-nav - +navdefaultlinks() - +navloginlogout() - section#mainpage - .container - .col-lg-6.col-lg-offset-3.col-md-6.col-md-offset-3 - h3 Recover Password - if recovered - .alert.alert-success.center.messagebox - strong Your password has been changed - p Your account has been assigned the temporary password#{recoverPw}
. You may now use this password to log in and choose a new password by visiting the change password/email page.
- else
- .alert.alert-danger.center.messagebox
- strong Password recovery failed
- p= recoverErr
- include footer
- +footer()
+extends layout.pug
+
+block content
+ .col-lg-6.col-lg-offset-3.col-md-6.col-md-offset-3
+ h3 Recover Password
+ if recovered
+ .alert.alert-success.center.messagebox
+ strong Your password has been changed
+ p Your account has been assigned the temporary password #{recoverPw}
. You may now use this password to log in and choose a new password by visiting the change password/email page.
+ else
+ .alert.alert-danger.center.messagebox
+ strong Password recovery failed
+ p= recoverErr
diff --git a/templates/account-passwordreset.pug b/templates/account-passwordreset.pug
index ee536c2e..4b597c6f 100644
--- a/templates/account-passwordreset.pug
+++ b/templates/account-passwordreset.pug
@@ -1,38 +1,22 @@
-doctype html
-html(lang="en")
- head
- include head
- +head()
- body
- #wrap
- nav.navbar.navbar-inverse.navbar-fixed-top(role="navigation")
- include nav
- +navheader()
- #nav-collapsible.collapse.navbar-collapse
- ul.nav.navbar-nav
- +navdefaultlinks()
- +navloginlogout()
- section#mainpage
- .container
- .col-lg-6.col-lg-offset-3.col-md-6.col-md-offset-3
- h3 Reset Password
- if reset
- .alert.alert-success.center.messagebox
- strong Password reset request sent
- p Please check #{resetEmail} for your recovery link.
- else if resetErr
- .alert.alert-danger.center.messagebox
- strong Error
- p= resetErr
- form(action="/account/passwordreset", method="post", role="form")
- input(type="hidden", name="_csrf", value=csrfToken)
- .form-group
- label.control-label(for="username") Username
- input#username.form-control(type="text", name="name")
- .form-group
- label.control-label(for="email") Email address
- input#email.form-control(type="email", name="email")
- button.btn.btn-primary.btn-block(type="submit") Send reset request
+extends layout.pug
- include footer
- +footer()
+block content
+ .col-lg-6.col-lg-offset-3.col-md-6.col-md-offset-3
+ h3 Reset Password
+ if reset
+ .alert.alert-success.center.messagebox
+ strong Password reset request sent
+ p Please check #{resetEmail} for your recovery link.
+ else if resetErr
+ .alert.alert-danger.center.messagebox
+ strong Error
+ p= resetErr
+ form(action="/account/passwordreset", method="post", role="form")
+ input(type="hidden", name="_csrf", value=csrfToken)
+ .form-group
+ label.control-label(for="username") Username
+ input#username.form-control(type="text", name="name")
+ .form-group
+ label.control-label(for="email") Email address
+ input#email.form-control(type="email", name="email")
+ button.btn.btn-primary.btn-block(type="submit") Send reset request
diff --git a/templates/account-profile.pug b/templates/account-profile.pug
index 3ecb9b05..f768a83e 100644
--- a/templates/account-profile.pug
+++ b/templates/account-profile.pug
@@ -1,76 +1,62 @@
-doctype html
-html(lang="en")
- head
- include head
- +head()
- body
- #wrap
- nav.navbar.navbar-inverse.navbar-fixed-top(role="navigation")
- include nav
- +navheader()
- #nav-collapsible.collapse.navbar-collapse
- ul.nav.navbar-nav
- +navdefaultlinks()
- +navloginlogout()
- section#mainpage
- .container
- if !loggedIn
- .col-lg-6.col-lg-offset-3.col-md-6.col-md-offset-3
- .alert.alert-danger.messagebox.center
- strong Authorization Required
- p You must be logged in to view this page.
- else
- .col-lg-6.col-lg-offset-3.col-md-6.col-md-offset-3
- h3 Profile
- if profileError
- .alert.alert-danger.center.messagebox
- strong Profile Error
- p= profileError
- .profile-box.linewrap(style="position: inherit; z-index: auto;")
- img.profile-image(src=profileImage)
- strong= loginName
- p= profileText
- h3 Edit Profile
- form(action="/account/profile", method="post", role="form")
- input(type="hidden", name="_csrf", value=csrfToken)
- .form-group
- label.control-label(for="profileimage") Image
- input#profileimage.form-control(type="text", name="image", maxlength="255")
- .form-group
- label.control-label(for="profiletext") Text
- textarea#profiletext.form-control(cols="10", name="text", maxlength="255")= profileText
- button.btn.btn-primary.btn-block(type="submit") Save
+extends layout.pug
- include footer
- +footer()
- script(type="text/javascript").
- var $profileImage = $("#profileimage");
- $profileImage.val("#{profileImage}");
- var hasError = false;
- function validateImage() {
- var value = $profileImage.val().trim();
- $profileImage.val(value);
- if (!/^$|^https:/.test(value)) {
- hasError = true;
- $profileImage.parent().addClass("has-error");
- var $error = $("#profileimage-error");
- if ($error.length === 0) {
- $error = $("")
- .attr({ id: "profileimage-error" })
- .addClass("text-danger")
- .html("Profile image must be a URL beginning with https://
")
- .insertAfter($profileImage);
- }
- } else {
- hasError = false;
- $profileImage.parent().removeClass("has-error");
- $("#profileimage-error").remove();
+block content
+ if !loggedIn
+ .col-lg-6.col-lg-offset-3.col-md-6.col-md-offset-3
+ .alert.alert-danger.messagebox.center
+ strong Authorization Required
+ p You must be logged in to view this page.
+ else
+ .col-lg-6.col-lg-offset-3.col-md-6.col-md-offset-3
+ h3 Profile
+ if profileError
+ .alert.alert-danger.center.messagebox
+ strong Profile Error
+ p= profileError
+ .profile-box.linewrap(style="position: inherit; z-index: auto;")
+ img.profile-image(src=profileImage)
+ strong= loginName
+ p= profileText
+ h3 Edit Profile
+ form(action="/account/profile", method="post", role="form")
+ input(type="hidden", name="_csrf", value=csrfToken)
+ .form-group
+ label.control-label(for="profileimage") Image
+ input#profileimage.form-control(type="text", name="image", maxlength="255")
+ .form-group
+ label.control-label(for="profiletext") Text
+ textarea#profiletext.form-control(cols="10", name="text", maxlength="255")= profileText
+ button.btn.btn-primary.btn-block(type="submit") Save
+
+append footer
+ script(type="text/javascript").
+ var $profileImage = $("#profileimage");
+ $profileImage.val("#{profileImage}");
+ var hasError = false;
+ function validateImage() {
+ var value = $profileImage.val().trim();
+ $profileImage.val(value);
+ if (!/^$|^https:/.test(value)) {
+ hasError = true;
+ $profileImage.parent().addClass("has-error");
+ var $error = $("#profileimage-error");
+ if ($error.length === 0) {
+ $error = $("")
+ .attr({ id: "profileimage-error" })
+ .addClass("text-danger")
+ .html("Profile image must be a URL beginning with https://
")
+ .insertAfter($profileImage);
}
+ } else {
+ hasError = false;
+ $profileImage.parent().removeClass("has-error");
+ $("#profileimage-error").remove();
}
+ }
- $("form").submit(function (event) {
- validateImage();
- if (hasError) {
- event.preventDefault();
- }
- });
+ $("form").submit(function (event) {
+ validateImage();
+ if (hasError) {
+ event.preventDefault();
+ }
+ });
diff --git a/templates/contact.pug b/templates/contact.pug
index a69556bb..67f2cd37 100644
--- a/templates/contact.pug
+++ b/templates/contact.pug
@@ -1,47 +1,34 @@
+extends layout.pug
+
mixin email(e, k)
button.btn.btn-xs.btn-default(onclick="showEmail(this, '"+e+"', '"+k+"')") Show Email
-doctype html
-html(lang="en")
- head
- include head
- +head()
- body
- #wrap
- nav.navbar.navbar-inverse.navbar-fixed-top(role="navigation")
- include nav
- +navheader()
- #nav-collapsible.collapse.navbar-collapse
- ul.nav.navbar-nav
- +navdefaultlinks()
- +navloginlogout()
- section#mainpage
- .container
- .col-md-8.col-md-offset-2
- h1 Contact
- h3 Email
- if contacts.length == 0
- p No contacts listed.
- else
- each contact in contacts
- strong= contact.name
- p.text-muted= contact.title
- +email(contact.email, contact.emkey)
- br
- hr
- include footer
- +footer()
- script(type="text/javascript").
- function showEmail(btn, email, key) {
- email = unescape(email);
- key = unescape(key);
- var dest = new Array(email.length);
- for (var i = 0; i < email.length; i++) {
- dest[i] = String.fromCharCode(email.charCodeAt(i) ^ key.charCodeAt(i % key.length));
- }
- email = dest.join("");
- $("").attr("href", "mailto:" + email)
- .text(email)
- .insertBefore(btn);
- $(btn).remove();
+block content
+ .col-md-8.col-md-offset-2
+ h1 Contact
+ h3 Email
+ if contacts.length == 0
+ p No contacts listed.
+ else
+ each contact in contacts
+ strong= contact.name
+ p.text-muted= contact.title
+ +email(contact.email, contact.emkey)
+ br
+ hr
+
+append footer
+ script(type="text/javascript").
+ function showEmail(btn, email, key) {
+ email = unescape(email);
+ key = unescape(key);
+ var dest = new Array(email.length);
+ for (var i = 0; i < email.length; i++) {
+ dest[i] = String.fromCharCode(email.charCodeAt(i) ^ key.charCodeAt(i % key.length));
}
+ email = dest.join("");
+ $("").attr("href", "mailto:" + email)
+ .text(email)
+ .insertBefore(btn);
+ $(btn).remove();
+ }
diff --git a/templates/csrferror.pug b/templates/csrferror.pug
index 37da5485..0193ad25 100644
--- a/templates/csrferror.pug
+++ b/templates/csrferror.pug
@@ -1,31 +1,15 @@
-doctype html
-html(lang="en")
- head
- include head
- +head()
- body
- #wrap
- nav.navbar.navbar-inverse.navbar-fixed-top(role="navigation")
- include nav
- +navheader()
- #nav-collapsible.collapse.navbar-collapse
- ul.nav.navbar-nav
- +navdefaultlinks()
- +navloginlogout()
+extends layout.pug
- section#mainpage.container
- .col-md-12
- .alert.alert-danger
- h1 Invalid Session
- p Your browser attempted to submit form data to #{path}
with an invalid authentication token. This may be because:
- ul
- li Your session has expired
- li Your request was missing the authentication token
- li A malicious user has attempted to tamper with your session
- li Your browser does not support cookies, or they are not enabled
- | If the problem persists, please contact an administrator.
- if referer
- a(href=referer) Return to previous page
-
- include footer
- +footer()
+block content
+ .col-md-12
+ .alert.alert-danger
+ h1 Invalid Session
+ p Your browser attempted to submit form data to #{path}
with an invalid authentication token. This may be because:
+ ul
+ li Your session has expired
+ li Your request was missing the authentication token
+ li A malicious user has attempted to tamper with your session
+ li Your browser does not support cookies, or they are not enabled
+ | If the problem persists, please contact an administrator.
+ if referer
+ a(href=referer) Return to previous page
diff --git a/templates/google_drive_userscript.pug b/templates/google_drive_userscript.pug
index c0a1a45b..e7e15ea4 100644
--- a/templates/google_drive_userscript.pug
+++ b/templates/google_drive_userscript.pug
@@ -1,60 +1,44 @@
-doctype html
-html(lang="en")
- head
- include head
- +head()
- body
- #wrap
- nav.navbar.navbar-inverse.navbar-fixed-top(role="navigation")
- include nav
- +navheader()
- #nav-collapsible.collapse.navbar-collapse
- ul.nav.navbar-nav
- +navdefaultlinks()
- +navloginlogout()
- section#mainpage
- .container
- .col-md-8.col-md-offset-2
- h1 Google Drive Userscript
- h2 Why?
- p.
- Since Google Drive support was launched in early 2014, it has broken
- at least 4-5 times, requiring increasing effort to get it working again
- and disrupting many channels. This is because there is no official API
- for it like there is for YouTube videos, which means support for it
- relies on undocumented tricks. In August 2016, the decision was made
- to phase out the native support for Google Drive and instead require
- users to install a userscript, which allows to bypass certain browser
- restrictions and make the code easier, simpler, and less prone to failure
- (it could still break due to future Google Drive changes, but is less
- likely to be difficult to fix).
- h2 How It Works
- p.
- The userscript is a short script that you can install using a browser
- extension such as Greasemonkey or Tampermonkey that runs on the page
- and provides additional functionality needed to play Google Drive
- videos.
- h2 Installation
- ul
- li
- strong Chrome
- | —Install Tampermonkey.
- li
- strong Firefox
- | —Install Tampermonkey
- | or Greasemonkey.
- li
- strong Other Browsers
- | —Install the appropriate userscript plugin for your browser.
- | Tampermonkey supports many browsers besides Chrome.
- p.
- Once you have installed the userscript manager addon for your browser,
- you can
- install the userscript. If this link 404s, it means the administrator
- of this server hasn't generated it yet.
- p.
- You can find a guide with screenshots of the installation process
- on GitHub.
+extends layout.pug
- include footer
- +footer()
+block content
+ .col-md-8.col-md-offset-2
+ h1 Google Drive Userscript
+ h2 Why?
+ p.
+ Since Google Drive support was launched in early 2014, it has broken
+ at least 4-5 times, requiring increasing effort to get it working again
+ and disrupting many channels. This is because there is no official API
+ for it like there is for YouTube videos, which means support for it
+ relies on undocumented tricks. In August 2016, the decision was made
+ to phase out the native support for Google Drive and instead require
+ users to install a userscript, which allows to bypass certain browser
+ restrictions and make the code easier, simpler, and less prone to failure
+ (it could still break due to future Google Drive changes, but is less
+ likely to be difficult to fix).
+ h2 How It Works
+ p.
+ The userscript is a short script that you can install using a browser
+ extension such as Greasemonkey or Tampermonkey that runs on the page
+ and provides additional functionality needed to play Google Drive
+ videos.
+ h2 Installation
+ ul
+ li
+ strong Chrome
+ | —Install Tampermonkey.
+ li
+ strong Firefox
+ | —Install Tampermonkey
+ | or Greasemonkey.
+ li
+ strong Other Browsers
+ | —Install the appropriate userscript plugin for your browser.
+ | Tampermonkey supports many browsers besides Chrome.
+ p.
+ Once you have installed the userscript manager addon for your browser,
+ you can
+ install the userscript. If this link 404s, it means the administrator
+ of this server hasn't generated it yet.
+ p.
+ You can find a guide with screenshots of the installation process
+ on GitHub.
diff --git a/templates/httperror.pug b/templates/httperror.pug
index 1e922f4d..5ce51b88 100644
--- a/templates/httperror.pug
+++ b/templates/httperror.pug
@@ -1,3 +1,5 @@
+extends layout.pug
+
mixin notfound()
h1 Not Found
p The page you were looking for doesn't seem to exist. Please check that you typed the URL correctly.
@@ -9,30 +11,13 @@ mixin forbidden()
mixin genericerror()
h1 Oops
p Your request could not be processed. Status code: #{status}
, message: #{message}
-doctype html
-html(lang="en")
- head
- include head
- +head()
- body
- #wrap
- nav.navbar.navbar-inverse.navbar-fixed-top(role="navigation")
- include nav
- +navheader()
- #nav-collapsible.collapse.navbar-collapse
- ul.nav.navbar-nav
- +navdefaultlinks()
- +navloginlogout()
- section#mainpage.container
- .col-md-12
- .alert.alert-danger
- if status == 404
- +notfound()
- else if status == 403
- +forbidden()
- else
- +genericerror()
-
- include footer
- +footer()
+block content
+ .col-md-12
+ .alert.alert-danger
+ if status == 404
+ +notfound()
+ else if status == 403
+ +forbidden()
+ else
+ +genericerror()
diff --git a/templates/index.pug b/templates/index.pug
index 794ee4e4..8c9a7833 100644
--- a/templates/index.pug
+++ b/templates/index.pug
@@ -1,42 +1,26 @@
-doctype html
-html(lang="en")
- head
- include head
- +head()
- body
- #wrap
- nav.navbar.navbar-inverse.navbar-fixed-top(role="navigation")
- include nav
- +navheader()
- #nav-collapsible.collapse.navbar-collapse
- ul.nav.navbar-nav
- +navdefaultlinks()
- +navsuperadmin(false)
- +navloginlogout()
- section#mainpage
- .container
- .col-lg-9.col-md-9
- h3 Public Channels
- table.table.table-bordered.table-striped
- thead
- th Channel
- th # Connected
- th Now Playing
- tbody
- each chan in channels
- tr
- td: a(href=`/${channelPath}/${chan.name}`) #{chan.pagetitle} (#{chan.name})
- td= chan.usercount
- td= chan.mediatitle
- .col-lg-3.col-md-3
- h3 Enter Channel
- input#channelname.form-control(type="text", placeholder="Channel Name")
- p.text-muted New channels can be registered from the My Channels page.
- include footer
- +footer()
- script(type="text/javascript").
- $("#channelname").keydown(function (ev) {
- if (ev.keyCode === 13) {
- location.href = "/#{channelPath}/" + $("#channelname").val();
- }
- });
+extends layout.pug
+
+block content
+ .col-lg-9.col-md-9
+ h3 Public Channels
+ table.table.table-bordered.table-striped
+ thead
+ th Channel
+ th # Connected
+ th Now Playing
+ tbody
+ each chan in channels
+ tr
+ td: a(href=`/${channelPath}/${chan.name}`) #{chan.pagetitle} (#{chan.name})
+ td= chan.usercount
+ td= chan.mediatitle
+ .col-lg-3.col-md-3
+ h3 Enter Channel
+ input#channelname.form-control(type="text", placeholder="Channel Name")
+ p.text-muted New channels can be registered from the My Channels page.
+ script(type="text/javascript").
+ $("#channelname").keydown(function (ev) {
+ if (ev.keyCode === 13) {
+ location.href = "/#{channelPath}/" + $("#channelname").val();
+ }
+ });
diff --git a/templates/layout.pug b/templates/layout.pug
new file mode 100644
index 00000000..aa1b2192
--- /dev/null
+++ b/templates/layout.pug
@@ -0,0 +1,22 @@
+doctype html
+html(lang="en")
+ head
+ block head
+ include head
+ +head()
+ body
+ #wrap
+ nav.navbar.navbar-inverse.navbar-fixed-top(role="navigation")
+ include nav
+ +navheader()
+ #nav-collapsible.collapse.navbar-collapse
+ ul.nav.navbar-nav
+ +navdefaultlinks()
+ +navsuperadmin(false)
+ +navloginlogout()
+ section#mainpage
+ .container
+ block content
+ block footer
+ include footer
+ +footer()
diff --git a/templates/login.pug b/templates/login.pug
index f5125437..37181ad7 100644
--- a/templates/login.pug
+++ b/templates/login.pug
@@ -1,54 +1,39 @@
-doctype html
-html(lang="en")
- head
- include head
- +head()
- body
- #wrap
- nav.navbar.navbar-inverse.navbar-fixed-top(role="navigation")
- include nav
- +navheader()
- #nav-collapsible.collapse.navbar-collapse
- ul.nav.navbar-nav
- +navdefaultlinks()
- if loggedIn
- +navlogoutform()
- section#mainpage.container
- if wasAlreadyLoggedIn
- .col-lg-6.col-lg-offset-3.col-md-6.col-md-offset-3
- .alert.alert-info.messagebox.center
- h3(style="margin: 5px auto") Logged in as #{loginName}
- else if !loggedIn
- .col-lg-6.col-lg-offset-3.col-md-6.col-md-offset-3
- if loginError
- .alert.alert-danger.messagebox.center
- strong Login Failed
- p= loginError
- h2 Login
- form(role="form", action="/login", method="post")
- input(type="hidden", name="_csrf", value=csrfToken)
- if redirect
- input(type="hidden", name="dest", value=redirect)
- .form-group
- label(for="username") Username
- input#username.form-control(type="text", name="name")
- .form-group
- label(for="password") Password
- input#password.form-control(type="password", name="password")
- a(href="/account/passwordreset") Forgot password?
- .form-group
- .checkbox
- label
- input(type="checkbox", name="remember")
- | Remember me
- button.btn.btn-success.btn-block(type="submit") Login
- else
- .col-lg-6.col-lg-offset-3.col-md-6.col-md-offset-3
- .alert.alert-success.messagebox.center
- strong Login Successful
- p Logged in as #{loginName}
- if redirect
- br
- a(href=redirect) Return to previous page
- include footer
- +footer()
+extends layout.pug
+
+block content
+ if wasAlreadyLoggedIn
+ .col-lg-6.col-lg-offset-3.col-md-6.col-md-offset-3
+ .alert.alert-info.messagebox.center
+ h3(style="margin: 5px auto") Logged in as #{loginName}
+ else if !loggedIn
+ .col-lg-6.col-lg-offset-3.col-md-6.col-md-offset-3
+ if loginError
+ .alert.alert-danger.messagebox.center
+ strong Login Failed
+ p= loginError
+ h2 Login
+ form(role="form", action="/login", method="post")
+ input(type="hidden", name="_csrf", value=csrfToken)
+ if redirect
+ input(type="hidden", name="dest", value=redirect)
+ .form-group
+ label(for="username") Username
+ input#username.form-control(type="text", name="name")
+ .form-group
+ label(for="password") Password
+ input#password.form-control(type="password", name="password")
+ a(href="/account/passwordreset") Forgot password?
+ .form-group
+ .checkbox
+ label
+ input(type="checkbox", name="remember")
+ | Remember me
+ button.btn.btn-success.btn-block(type="submit") Login
+ else
+ .col-lg-6.col-lg-offset-3.col-md-6.col-md-offset-3
+ .alert.alert-success.messagebox.center
+ strong Login Successful
+ p Logged in as #{loginName}
+ if redirect
+ br
+ a(href=redirect) Return to previous page
diff --git a/templates/logout.pug b/templates/logout.pug
index fbddb942..a564e2c3 100644
--- a/templates/logout.pug
+++ b/templates/logout.pug
@@ -1,23 +1,9 @@
-doctype html
-html(lang="en")
- head
- include head
- +head()
- body
- #wrap
- nav.navbar.navbar-inverse.navbar-fixed-top(role="navigation")
- include nav
- +navheader()
- #nav-collapsible.collapse.navbar-collapse
- ul.nav.navbar-nav
- +navdefaultlinks()
- +navloginform("/")
- section#mainpage.container
- .col-lg-6.col-lg-offset-3.col-md-6.col-md-offset-3
- .alert.alert-info.center.messagebox
- strong Logged out
- p
- if redirect
- a(href=redirect) Return to previous page
- include footer
- +footer()
+extends layout.pug
+
+block content
+ .col-lg-6.col-lg-offset-3.col-md-6.col-md-offset-3
+ .alert.alert-info.center.messagebox
+ strong Logged out
+ p
+ if redirect
+ a(href=redirect) Return to previous page
diff --git a/templates/register.pug b/templates/register.pug
index 1061dbc7..be0d81d3 100644
--- a/templates/register.pug
+++ b/templates/register.pug
@@ -1,127 +1,114 @@
-doctype html
-html(lang="en")
- head
- include head
- +head()
- body
- #wrap
- nav.navbar.navbar-inverse.navbar-fixed-top(role="navigation")
- include nav
- +navheader()
- #nav-collapsible.collapse.navbar-collapse
- ul.nav.navbar-nav
- +navdefaultlinks()
- if loggedIn
- +navlogoutform()
- section#mainpage.container
- if loggedIn
- .col-lg-6.col-lg-offset-3.col-md-6.col-md-offset-3
- .alert.alert-danger.messagebox.center
- strong Already logged in
- p.
- You are already logged in. If you intend to register a new account, please Logout first.
- // TODO Link to My Account page
- else if !registered
- .col-lg-6.col-lg-offset-3.col-md-6.col-md-offset-3
- if registerError
- .alert.alert-danger.messagebox.center
- strong Registration Failed
- p= registerError
- h2 Register
- form(role="form", action="/register", method="post", onsubmit="return verify()")
- input(type="hidden", name="_csrf", value=csrfToken)
- .form-group
- label.control-label(for="username") Username
- input#username.form-control(type="text", name="name", onkeyup="checkUsername()", maxlength="20")
- p#validate_username.text-danger.pull-right
- .form-group
- label.control-label(for="password") Password
- input#password.form-control(type="password", name="password", onkeyup="checkPasswords()")
- p#validate_password.text-danger.pull-right
- .form-group
- label.control-label(for="password_confirm") Confirm Password
- input#password_confirm.form-control(type="password", onkeyup="checkPasswords()")
- p#validate_confirm.text-danger.pull-right
- .form-group
- label.control-label(for="email") Email (optional)
- input#email.form-control(type="email", name="email")
- p#validate_email.text-danger.pull-right
- p
- | Providing an email address is optional and will allow you to recover your account via email if you forget your password.
- strong If you do not provide an email address, you will not be able to recover a lost account!
- button#registerbtn.btn.btn-success.btn-block(type="submit") Register
- else
- .col-lg-6.col-lg-offset-3.col-md-6.col-md-offset-3
- .alert.alert-success.messagebox.center
- strong Registration Successful
- p Thanks for registering, #{registerName}! Now you can Login to use your account.
- include footer
- +footer()
- script(type="text/javascript").
- function verify() {
- var valid = checkUsername();
- valid = checkPasswords() && valid;
- valid = checkEmail() && valid;
- return valid;
- }
- function checkUsername() {
- function stateError(text){
- target.parent()
- .addClass("has-error")
- .removeClass("has-success");
- $("#validate_username").text(text);
- }
- var target = $("#username");
- var name = target.val();
- if (name === "") {
- stateError('Username must not be empty')
- return false;
- } else if (!(/^[-\w\u00c0-\u00ff]{1,20}$/).test(name)) {
- stateError("Username must consist of 1-20 characters" +
- " a-Z, A-Z, 0-9, -, or _.");
- return false;
- } else {
- target.parent()
- .removeClass("has-error")
- .addClass("has-success");
- $("#validate_username").text('');
- }
- }
- function checkPasswords() {
- function stateError(text, target, validator){
- target.parent()
- .addClass("has-error")
- .removeClass("has-success");
- $(`#${validator}`).text(text);
- }
- var target = $("#password");
- var target2 = $("#password_confirm");
- var pw = target.val();
- var pwc = target2.val();
+extends layout.pug
- $("#validate_password").text('');
- $("#validate_confirm").text('');
- if (pw === "") {
- stateError('Password must not be empty', target, 'validate_password')
+block content
+ if loggedIn
+ .col-lg-6.col-lg-offset-3.col-md-6.col-md-offset-3
+ .alert.alert-danger.messagebox.center
+ strong Already logged in
+ p.
+ You are already logged in. If you intend to register a new account, please Logout first.
+ // TODO Link to My Account page
+ else if !registered
+ .col-lg-6.col-lg-offset-3.col-md-6.col-md-offset-3
+ if registerError
+ .alert.alert-danger.messagebox.center
+ strong Registration Failed
+ p= registerError
+ h2 Register
+ form(role="form", action="/register", method="post", onsubmit="return verify()")
+ input(type="hidden", name="_csrf", value=csrfToken)
+ .form-group
+ label.control-label(for="username") Username
+ input#register-username.form-control(type="text", name="name", onkeyup="checkUsername()", maxlength="20")
+ p#validate_username.text-danger.pull-right
+ .form-group
+ label.control-label(for="password") Password
+ input#register-password.form-control(type="password", name="password", onkeyup="checkPasswords()")
+ p#validate_password.text-danger.pull-right
+ .form-group
+ label.control-label(for="password_confirm") Confirm Password
+ input#register-password-confirm.form-control(type="password", onkeyup="checkPasswords()")
+ p#validate_confirm.text-danger.pull-right
+ .form-group
+ label.control-label(for="email") Email (optional)
+ input#register-email.form-control(type="email", name="email")
+ p#validate_email.text-danger.pull-right
+ p
+ | Providing an email address is optional and will allow you to recover your account via email if you forget your password.
+ strong If you do not provide an email address, you will not be able to recover a lost account!
+ button#registerbtn.btn.btn-success.btn-block(type="submit") Register
+ else
+ .col-lg-6.col-lg-offset-3.col-md-6.col-md-offset-3
+ .alert.alert-success.messagebox.center
+ strong Registration Successful
+ p Thanks for registering, #{registerName}! Now you can Login to use your account.
+
+append footer
+ script(type="text/javascript").
+ function verify() {
+ var valid = checkUsername();
+ valid = checkPasswords() && valid;
+ valid = checkEmail() && valid;
+ return valid;
+ }
+ function checkUsername() {
+ function stateError(text){
+ target.parent()
+ .addClass("has-error")
+ .removeClass("has-success");
+ $("#validate_username").text(text);
+ }
+ var target = $("#register-username");
+ var name = target.val();
+ if (name === "") {
+ stateError('Username must not be empty')
+ return false;
+ } else if (!(/^[-\w\u00c0-\u00ff]{1,20}$/).test(name)) {
+ stateError("Username must consist of 1-20 characters" +
+ " a-Z, A-Z, 0-9, -, or _.");
+ return false;
+ } else {
+ target.parent()
+ .removeClass("has-error")
+ .addClass("has-success");
+ $("#validate_username").text('');
+ }
+ }
+ function checkPasswords() {
+ function stateError(text, target, validator){
+ target.parent()
+ .addClass("has-error")
+ .removeClass("has-success");
+ $(`#${validator}`).text(text);
+ }
+ var target = $("#register-password");
+ var target2 = $("#register-password-confirm");
+ var pw = target.val();
+ var pwc = target2.val();
+
+ $("#validate_password").text('');
+ $("#validate_confirm").text('');
+ if (pw === "") {
+ stateError('Password must not be empty', target, 'validate_password')
+ return false;
+ } else {
+ target.parent()
+ .removeClass("has-error")
+ .addClass("has-success");
+ if (pw !== pwc) {
+ stateError('Passwords do not match', target2, 'validate_confirm')
return false;
} else {
- target.parent()
+ target2.parent()
.removeClass("has-error")
.addClass("has-success");
- if (pw !== pwc) {
- stateError('Passwords do not match', target2, 'validate_confirm')
- return false;
- } else {
- target2.parent()
- .removeClass("has-error")
- .addClass("has-success");
- }
}
}
- function checkEmail() {
- var email = $("#email").val();
- if (email.trim() === "") {
- return confirm("Are you sure you want to register without setting a recovery email address? If you lose the password, or if your account is compromised, you WILL NOT be able to recover it.");
- }
- return true;
+ }
+ function checkEmail() {
+ var email = $("#register-email").val();
+ if (email.trim() === "") {
+ return confirm("Are you sure you want to register without setting a recovery email address? If you lose the password, or if your account is compromised, you WILL NOT be able to recover it.");
}
+ return true;
+ }