From 7749c754bcc4708133c259ce7c6f05f4b57fcb2d Mon Sep 17 00:00:00 2001 From: Butter Cat Date: Thu, 16 Nov 2023 21:51:11 -0500 Subject: [PATCH 1/4] Make hls playback work without inline JS --- public/js/hlsPlayback.js | 45 ++++++++++++++++++++++------------------ src/views/tweet.nim | 2 +- 2 files changed, 26 insertions(+), 21 deletions(-) diff --git a/public/js/hlsPlayback.js b/public/js/hlsPlayback.js index 5cd46a6..e3435bc 100644 --- a/public/js/hlsPlayback.js +++ b/public/js/hlsPlayback.js @@ -1,25 +1,30 @@ // @license http://www.gnu.org/licenses/agpl-3.0.html AGPL-3.0 // SPDX-License-Identifier: AGPL-3.0-only -function playVideo(overlay) { - const video = overlay.parentElement.querySelector('video'); - const url = video.getAttribute("data-url"); - video.setAttribute("controls", ""); - overlay.style.display = "none"; +const video_overlay = document.getElementsByClassName("video-overlay"); - if (Hls.isSupported()) { - var hls = new Hls({autoStartLoad: false}); - hls.loadSource(url); - hls.attachMedia(video); - hls.on(Hls.Events.MANIFEST_PARSED, function () { - hls.loadLevel = hls.levels.length - 1; - hls.startLoad(); - video.play(); - }); - } else if (video.canPlayType('application/vnd.apple.mpegurl')) { - video.src = url; - video.addEventListener('canplay', function() { - video.play(); - }); - } +for (var i = 0 ; i < video_overlay.length; i++) { + video_overlay[i].addEventListener('click', function () { + + const video = this.parentElement.querySelector('video'); + const url = video.getAttribute("data-url"); + video.setAttribute("controls", ""); + this.style.display = "none"; + + if (Hls.isSupported()) { + var hls = new Hls({autoStartLoad: false}); + hls.loadSource(url); + hls.attachMedia(video); + hls.on(Hls.Events.MANIFEST_PARSED, function () { + hls.loadLevel = hls.levels.length - 1; + hls.startLoad(); + video.play(); + }); + } else if (video.canPlayType('application/vnd.apple.mpegurl')) { + video.src = url; + video.addEventListener('canplay', function() { + video.play(); + }); + } + }); } // @license-end diff --git a/src/views/tweet.nim b/src/views/tweet.nim index f47ae9a..c9bf06a 100644 --- a/src/views/tweet.nim +++ b/src/views/tweet.nim @@ -109,7 +109,7 @@ proc renderVideo*(video: Video; prefs: Prefs; path: string): VNode = source(src=source, `type`="video/mp4") of m3u8, vmap: video(poster=thumb, data-url=source, data-autoload="false", muted=prefs.muteVideos) - verbatim "
" + verbatim "
" tdiv(class="overlay-circle"): span(class="overlay-triangle") verbatim "
" if container.len > 0: From 5eb010e7cd716e41d5ad6b8e20406200945debb3 Mon Sep 17 00:00:00 2001 From: Butter Cat Date: Fri, 17 Nov 2023 08:57:30 -0500 Subject: [PATCH 2/4] Make hls playback function with infinite scroll again --- public/js/hlsPlayback.js | 58 +++++++++++++++++++++++----------------- 1 file changed, 34 insertions(+), 24 deletions(-) diff --git a/public/js/hlsPlayback.js b/public/js/hlsPlayback.js index e3435bc..c1111fd 100644 --- a/public/js/hlsPlayback.js +++ b/public/js/hlsPlayback.js @@ -1,30 +1,40 @@ // @license http://www.gnu.org/licenses/agpl-3.0.html AGPL-3.0 // SPDX-License-Identifier: AGPL-3.0-only -const video_overlay = document.getElementsByClassName("video-overlay"); +function playVideo() { + const video_overlay = document.getElementsByClassName("video-overlay"); + + for (var i = 0 ; i < video_overlay.length; i++) { + video_overlay[i].addEventListener('click', function () { -for (var i = 0 ; i < video_overlay.length; i++) { - video_overlay[i].addEventListener('click', function () { + const video = this.parentElement.querySelector('video'); + const url = video.getAttribute("data-url"); + video.setAttribute("controls", ""); + this.style.display = "none"; - const video = this.parentElement.querySelector('video'); - const url = video.getAttribute("data-url"); - video.setAttribute("controls", ""); - this.style.display = "none"; - - if (Hls.isSupported()) { - var hls = new Hls({autoStartLoad: false}); - hls.loadSource(url); - hls.attachMedia(video); - hls.on(Hls.Events.MANIFEST_PARSED, function () { - hls.loadLevel = hls.levels.length - 1; - hls.startLoad(); - video.play(); - }); - } else if (video.canPlayType('application/vnd.apple.mpegurl')) { - video.src = url; - video.addEventListener('canplay', function() { - video.play(); - }); - } - }); + if (Hls.isSupported()) { + var hls = new Hls({autoStartLoad: false}); + hls.loadSource(url); + hls.attachMedia(video); + hls.on(Hls.Events.MANIFEST_PARSED, function () { + hls.loadLevel = hls.levels.length - 1; + hls.startLoad(); + video.play(); + }); + } else if (video.canPlayType('application/vnd.apple.mpegurl')) { + video.src = url; + video.addEventListener('canplay', function() { + video.play(); + }); + } + }); + } } + +var observer = new MutationObserver(function () { + playVideo() +}); + +playVideo() + +observer.observe(document.body, {childList: true, subtree: true}); // @license-end From 289edc973cbee6e6cdfb97ee5c1c8b3b732e5c1f Mon Sep 17 00:00:00 2001 From: Butter Cat Date: Fri, 17 Nov 2023 09:29:24 -0500 Subject: [PATCH 3/4] Add support for using a nonce with the Content-Security-Policy header --- nitter.example.conf | 1 + src/config.nim | 1 + src/types.nim | 1 + src/views/general.nim | 6 +++--- 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/nitter.example.conf b/nitter.example.conf index f0b4214..4fbf20e 100644 --- a/nitter.example.conf +++ b/nitter.example.conf @@ -21,6 +21,7 @@ redisMaxConnections = 30 [Config] hmacKey = "secretkey" # random key for cryptographic signing of video urls +nonceString = "secretstring" # random string for the Content-Security-Policy header with script-src base64Media = false # use base64 encoding for proxied media urls enableRSS = true # set this to false to disable RSS feeds enableDebug = false # enable request logs and debug endpoints (/.accounts) diff --git a/src/config.nim b/src/config.nim index 1b05ffe..3e14a33 100644 --- a/src/config.nim +++ b/src/config.nim @@ -35,6 +35,7 @@ proc getConfig*(path: string): (Config, parseCfg.Config) = # Config hmacKey: cfg.get("Config", "hmacKey", "secretkey"), + nonceString: cfg.get("Config", "nonceString", "secretstring"), base64Media: cfg.get("Config", "base64Media", false), minTokens: cfg.get("Config", "tokenCount", 10), enableRss: cfg.get("Config", "enableRSS", true), diff --git a/src/types.nim b/src/types.nim index 3b0d55c..f1db729 100644 --- a/src/types.nim +++ b/src/types.nim @@ -256,6 +256,7 @@ type staticDir*: string hmacKey*: string + nonceString*: string base64Media*: bool minTokens*: int enableRss*: bool diff --git a/src/views/general.nim b/src/views/general.nim index 5e96d02..b161fd8 100644 --- a/src/views/general.nim +++ b/src/views/general.nim @@ -73,11 +73,11 @@ proc renderHead*(prefs: Prefs; cfg: Config; req: Request; titleText=""; desc=""; link(rel="alternate", type="application/rss+xml", href=rss, title="RSS feed") if prefs.hlsPlayback: - script(src="/js/hls.light.min.js", `defer`="") - script(src="/js/hlsPlayback.js", `defer`="") + script(nonce=cfg.nonceString, src="/js/hls.light.min.js", `defer`="") + script(nonce=cfg.nonceString, src="/js/hlsPlayback.js", `defer`="") if prefs.infiniteScroll: - script(src="/js/infiniteScroll.js", `defer`="") + script(nonce=cfg.nonceString, src="/js/infiniteScroll.js", `defer`="") title: if titleText.len > 0: From ea0b5d7b9dafbaf9fc77170c677e649f9148281a Mon Sep 17 00:00:00 2001 From: Butter Cat Date: Sat, 18 Nov 2023 14:42:54 +0000 Subject: [PATCH 4/4] Fix broken tab spacing Co-authored-by: Zed --- public/js/hlsPlayback.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/public/js/hlsPlayback.js b/public/js/hlsPlayback.js index c1111fd..ff05603 100644 --- a/public/js/hlsPlayback.js +++ b/public/js/hlsPlayback.js @@ -1,9 +1,9 @@ // @license http://www.gnu.org/licenses/agpl-3.0.html AGPL-3.0 // SPDX-License-Identifier: AGPL-3.0-only function playVideo() { - const video_overlay = document.getElementsByClassName("video-overlay"); + const video_overlay = document.getElementsByClassName("video-overlay"); - for (var i = 0 ; i < video_overlay.length; i++) { + for (var i = 0 ; i < video_overlay.length; i++) { video_overlay[i].addEventListener('click', function () { const video = this.parentElement.querySelector('video');