Date: Thu, 14 Sep 2023 22:10:02 +0200
Subject: [PATCH 096/455] Frontend: Add timestamp on switch invidious instance
links
---
assets/js/player.js | 26 ++++++++++++++++++++------
src/invidious/views/watch.ecr | 7 ++-----
2 files changed, 22 insertions(+), 11 deletions(-)
diff --git a/assets/js/player.js b/assets/js/player.js
index d07d6cf4..bffc7ad3 100644
--- a/assets/js/player.js
+++ b/assets/js/player.js
@@ -113,20 +113,34 @@ function addCurrentTimeToURL(url) {
}
/**
- * Timer that updates the timestamp on "watch on youtube" and "embed" links
+ * Timer that updates the timestamp on all external links
*/
player.ready(function () {
+ // YouTube links
+
let elem_yt_watch = document.getElementById('link-yt-watch');
let elem_yt_embed = document.getElementById('link-yt-embed');
- let elem_iv_embed = document.getElementById('link-iv-embed');
let base_url_yt_watch = elem_yt_watch.getAttribute('data-base-url');
let base_url_yt_embed = elem_yt_embed.getAttribute('data-base-url');
- let base_url_iv_embed = elem_iv_embed.getAttribute('data-base-url');
- setTimeout(() => { elem_yt_watch.setAttribute('href') = addCurrentTimeToURL(base_url_yt_watch); }, 5000);
- setTimeout(() => { elem_yt_embed.setAttribute('href') = addCurrentTimeToURL(base_url_yt_embed); }, 5000);
- setTimeout(() => { elem_iv_embed.setAttribute('href') = addCurrentTimeToURL(base_url_iv_embed); }, 5000);
+ setTimeout(() => {
+ elem_yt_watch.setAttribute('href') = addCurrentTimeToURL(base_url_yt_watch);
+ elem_yt_embed.setAttribute('href') = addCurrentTimeToURL(base_url_yt_embed);
+ }, 5000);
+
+ // Invidious links
+
+ let elem_iv_embed = document.getElementById('link-iv-embed');
+ let elem_iv_other = document.getElementById('link-iv-other');
+
+ let base_url_iv_embed = elem_iv_embed.getAttribute('data-base-url');
+ let base_url_iv_other = elem_iv_other.getAttribute('data-base-url');
+
+ setTimeout(() => {
+ elem_iv_embed.setAttribute('href') = addCurrentTimeToURL(base_url_iv_embed);
+ elem_iv_other.setAttribute('href') = addCurrentTimeToURL(base_url_iv_other);
+ }, 5000);
});
diff --git a/src/invidious/views/watch.ecr b/src/invidious/views/watch.ecr
index a768328a..bf297a43 100644
--- a/src/invidious/views/watch.ecr
+++ b/src/invidious/views/watch.ecr
@@ -127,11 +127,8 @@ we're going to need to do it here in order to allow for translations.
- <% if env.get("preferences").as(Preferences).automatic_instance_redirect%>
- "><%= translate(locale, "Switch Invidious Instance") %>
- <% else %>
- <%= translate(locale, "Switch Invidious Instance") %>
- <% end %>
+ <%- link_iv_other = IV::Frontend::Misc.redirect_url(env) -%>
+ <%= translate(locale, "Switch Invidious Instance") %>
From 06b2a4ba9d8f480543c950059259da9b12e053ff Mon Sep 17 00:00:00 2001
From: Samantaz Fox
Date: Sat, 16 Sep 2023 00:41:39 +0200
Subject: [PATCH 097/455] Frontend: Use 'timeupdate' event listener rather than
setTimeout()
---
assets/js/player.js | 19 +++++++++----------
1 file changed, 9 insertions(+), 10 deletions(-)
diff --git a/assets/js/player.js b/assets/js/player.js
index bffc7ad3..8eae54f4 100644
--- a/assets/js/player.js
+++ b/assets/js/player.js
@@ -113,9 +113,12 @@ function addCurrentTimeToURL(url) {
}
/**
- * Timer that updates the timestamp on all external links
+ * Callback that updates the timestamp on all external links
*/
-player.ready(function () {
+player.on('timeupdate', function () {
+ // Only update once every 5 seconds
+ if ((Math.ceil(player.currentTime()) % 5) != 0) return;
+
// YouTube links
let elem_yt_watch = document.getElementById('link-yt-watch');
@@ -124,10 +127,8 @@ player.ready(function () {
let base_url_yt_watch = elem_yt_watch.getAttribute('data-base-url');
let base_url_yt_embed = elem_yt_embed.getAttribute('data-base-url');
- setTimeout(() => {
- elem_yt_watch.setAttribute('href') = addCurrentTimeToURL(base_url_yt_watch);
- elem_yt_embed.setAttribute('href') = addCurrentTimeToURL(base_url_yt_embed);
- }, 5000);
+ elem_yt_watch.setAttribute('href') = addCurrentTimeToURL(base_url_yt_watch);
+ elem_yt_embed.setAttribute('href') = addCurrentTimeToURL(base_url_yt_embed);
// Invidious links
@@ -137,10 +138,8 @@ player.ready(function () {
let base_url_iv_embed = elem_iv_embed.getAttribute('data-base-url');
let base_url_iv_other = elem_iv_other.getAttribute('data-base-url');
- setTimeout(() => {
- elem_iv_embed.setAttribute('href') = addCurrentTimeToURL(base_url_iv_embed);
- elem_iv_other.setAttribute('href') = addCurrentTimeToURL(base_url_iv_other);
- }, 5000);
+ elem_iv_embed.setAttribute('href') = addCurrentTimeToURL(base_url_iv_embed);
+ elem_iv_other.setAttribute('href') = addCurrentTimeToURL(base_url_iv_other);
});
From ebee973b2454f3e1adfab798ed8be6b9ef123069 Mon Sep 17 00:00:00 2001
From: Samantaz Fox
Date: Sat, 16 Sep 2023 00:54:14 +0200
Subject: [PATCH 098/455] Routes: Redirect unknown channel tabs to channel home
page
---
src/invidious/routes/channels.cr | 6 ++++++
src/invidious/routing.cr | 2 +-
2 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/src/invidious/routes/channels.cr b/src/invidious/routes/channels.cr
index 5500672f..d744712d 100644
--- a/src/invidious/routes/channels.cr
+++ b/src/invidious/routes/channels.cr
@@ -1,6 +1,12 @@
{% skip_file if flag?(:api_only) %}
module Invidious::Routes::Channels
+ # Redirection for unsupported routes ("tabs")
+ def self.redirect_home(env)
+ ucid = env.params.url["ucid"]
+ return env.redirect "/channel/#{URI.encode_www_form(ucid)}"
+ end
+
def self.home(env)
self.videos(env)
end
diff --git a/src/invidious/routing.cr b/src/invidious/routing.cr
index f6b3aaa6..8c38aaed 100644
--- a/src/invidious/routing.cr
+++ b/src/invidious/routing.cr
@@ -131,7 +131,7 @@ module Invidious::Routing
# Channel catch-all, to redirect future routes to the channel's home
# NOTE: defined last in order to be processed after the other routes
- get "/channel/:ucid/*", Routes::Channels, :home
+ get "/channel/:ucid/*", Routes::Channels, :redirect_home
# /c/LinusTechTips
get "/c/:user", Routes::Channels, :brand_redirect
From cc03610325f8c49b14216f2913a8a3148b48e3a2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C3=89milien=20=28perso=29?=
<4016501+unixfox@users.noreply.github.com>
Date: Sat, 16 Sep 2023 09:10:48 +0000
Subject: [PATCH 099/455] Test crystal 1.8.2
---
.github/workflows/ci.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 96903fc7..f94a943a 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -42,7 +42,7 @@ jobs:
- 1.5.1
- 1.6.2
- 1.7.3
- - 1.8.1
+ - 1.8.2
include:
- crystal: nightly
stable: false
From 33ce0ddf148c3537d93143afeaf458a474c6bf1b Mon Sep 17 00:00:00 2001
From: Samantaz Fox
Date: Sun, 10 Sep 2023 19:50:46 +0000
Subject: [PATCH 100/455] Update crystal version matrix in ci.yml
---
.github/workflows/ci.yml | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index f94a943a..2c115f13 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -38,11 +38,10 @@ jobs:
matrix:
stable: [true]
crystal:
- - 1.4.1
- - 1.5.1
- 1.6.2
- 1.7.3
- 1.8.2
+ - 1.9.2
include:
- crystal: nightly
stable: false
From bbf067ed55810bef6ee5550c66c38528d1ef8a32 Mon Sep 17 00:00:00 2001
From: Samantaz Fox
Date: Sun, 10 Sep 2023 22:15:33 +0200
Subject: [PATCH 101/455] Bump crystal-install too
---
.github/workflows/ci.yml | 2 +-
.github/workflows/container-release.yml | 5 ++---
2 files changed, 3 insertions(+), 4 deletions(-)
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 2c115f13..1ca0dc96 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -52,7 +52,7 @@ jobs:
submodules: true
- name: Install Crystal
- uses: crystal-lang/install-crystal@v1.7.0
+ uses: crystal-lang/install-crystal@v1.8.0
with:
crystal: ${{ matrix.crystal }}
diff --git a/.github/workflows/container-release.yml b/.github/workflows/container-release.yml
index 13bbf34c..c2756fcc 100644
--- a/.github/workflows/container-release.yml
+++ b/.github/workflows/container-release.yml
@@ -25,9 +25,9 @@ jobs:
uses: actions/checkout@v3
- name: Install Crystal
- uses: crystal-lang/install-crystal@v1.6.0
+ uses: crystal-lang/install-crystal@v1.8.0
with:
- crystal: 1.5.0
+ crystal: 1.9.2
- name: Run lint
run: |
@@ -77,4 +77,3 @@ jobs:
tags: quay.io/invidious/invidious:${{ github.sha }}-arm64,quay.io/invidious/invidious:latest-arm64
build-args: |
"release=1"
-
From 760bf4cfb310954eb649aa18ca9961c2c7f3ca51 Mon Sep 17 00:00:00 2001
From: syeopite <70992037+syeopite@users.noreply.github.com>
Date: Sat, 16 Sep 2023 23:22:49 +0000
Subject: [PATCH 102/455] Bump stale timer for PRs
---
.github/workflows/stale.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml
index a945da58..a7e218a2 100644
--- a/.github/workflows/stale.yml
+++ b/.github/workflows/stale.yml
@@ -14,7 +14,7 @@ jobs:
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
days-before-stale: 365
- days-before-pr-stale: 45 # PRs should be active. Anything that hasn't had activity in more than 45 days should be considered abandoned.
+ days-before-pr-stale: 90
days-before-close: 30
exempt-pr-labels: blocked
stale-issue-message: 'This issue has been automatically marked as stale and will be closed in 30 days because it has not had recent activity and is much likely outdated. If you think this issue is still relevant and applicable, you just have to post a comment and it will be unmarked.'
From 700c57559bb61f18657ba0d2a761b568dfdb509a Mon Sep 17 00:00:00 2001
From: Samantaz Fox
Date: Sun, 17 Sep 2023 10:21:11 +0000
Subject: [PATCH 103/455] JS: Replace '.setAttribute("href")' with '.href'
Co-authored-by: syeopite <70992037+syeopite@users.noreply.github.com>
---
assets/js/player.js | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/assets/js/player.js b/assets/js/player.js
index 8eae54f4..bed02875 100644
--- a/assets/js/player.js
+++ b/assets/js/player.js
@@ -127,8 +127,8 @@ player.on('timeupdate', function () {
let base_url_yt_watch = elem_yt_watch.getAttribute('data-base-url');
let base_url_yt_embed = elem_yt_embed.getAttribute('data-base-url');
- elem_yt_watch.setAttribute('href') = addCurrentTimeToURL(base_url_yt_watch);
- elem_yt_embed.setAttribute('href') = addCurrentTimeToURL(base_url_yt_embed);
+ elem_yt_watch.href = addCurrentTimeToURL(base_url_yt_watch);
+ elem_yt_embed.href = addCurrentTimeToURL(base_url_yt_embed);
// Invidious links
@@ -138,8 +138,8 @@ player.on('timeupdate', function () {
let base_url_iv_embed = elem_iv_embed.getAttribute('data-base-url');
let base_url_iv_other = elem_iv_other.getAttribute('data-base-url');
- elem_iv_embed.setAttribute('href') = addCurrentTimeToURL(base_url_iv_embed);
- elem_iv_other.setAttribute('href') = addCurrentTimeToURL(base_url_iv_other);
+ elem_iv_embed.href = addCurrentTimeToURL(base_url_iv_embed);
+ elem_iv_other.href = addCurrentTimeToURL(base_url_iv_other);
});
From 270d606ad8f8b17430165227c98c46d8495995e5 Mon Sep 17 00:00:00 2001
From: RadoslavL
Date: Mon, 18 Sep 2023 08:14:34 +0300
Subject: [PATCH 104/455] Changed the default dark theme as well
---
assets/css/default.css | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/assets/css/default.css b/assets/css/default.css
index c94ed9d8..ec037240 100644
--- a/assets/css/default.css
+++ b/assets/css/default.css
@@ -635,7 +635,7 @@ body.dark-theme {
}
.no-theme a {
- color: #a0a0a0;
+ color: #adadad;
text-decoration: none;
}
From e3c365f3d68985a8e3ce35f76d334c7184a548de Mon Sep 17 00:00:00 2001
From: ChunkyProgrammer <78101139+ChunkyProgrammer@users.noreply.github.com>
Date: Wed, 19 Jul 2023 12:35:22 -0700
Subject: [PATCH 105/455] Add support for post page
---
assets/css/default.css | 2 +-
assets/js/comments.js | 174 +++++++++++++++++++++
assets/js/post.js | 3 +
assets/js/watch.js | 157 -------------------
src/invidious/channels/community.cr | 39 ++++-
src/invidious/comments/youtube.cr | 51 +++++-
src/invidious/frontend/comments_youtube.cr | 18 +++
src/invidious/routes/api/v1/channels.cr | 47 ++++++
src/invidious/routes/api/v1/misc.cr | 10 +-
src/invidious/routes/channels.cr | 37 +++++
src/invidious/routing.cr | 6 +
src/invidious/views/community.ecr | 2 +-
src/invidious/views/post.ecr | 31 ++++
src/invidious/views/watch.ecr | 6 +-
14 files changed, 416 insertions(+), 167 deletions(-)
create mode 100644 assets/js/comments.js
create mode 100644 assets/js/post.js
create mode 100644 src/invidious/views/post.ecr
diff --git a/assets/css/default.css b/assets/css/default.css
index c31b24e5..69fe8d5f 100644
--- a/assets/css/default.css
+++ b/assets/css/default.css
@@ -392,7 +392,7 @@ p.video-data { margin: 0; font-weight: bold; font-size: 80%; }
* Comments & community posts
*/
-#comments {
+.comments {
max-width: 800px;
margin: auto;
}
diff --git a/assets/js/comments.js b/assets/js/comments.js
new file mode 100644
index 00000000..00a8cae9
--- /dev/null
+++ b/assets/js/comments.js
@@ -0,0 +1,174 @@
+var video_data = JSON.parse(document.getElementById('video_data').textContent);
+
+var spinnerHTML = '
';
+var spinnerHTMLwithHR = spinnerHTML + '
';
+
+String.prototype.supplant = function (o) {
+ return this.replace(/{([^{}]*)}/g, function (a, b) {
+ var r = o[b];
+ return typeof r === 'string' || typeof r === 'number' ? r : a;
+ });
+};
+
+function toggle_comments(event) {
+ var target = event.target;
+ var body = target.parentNode.parentNode.parentNode.children[1];
+ if (body.style.display === 'none') {
+ target.textContent = '[ − ]';
+ body.style.display = '';
+ } else {
+ target.textContent = '[ + ]';
+ body.style.display = 'none';
+ }
+}
+
+function hide_youtube_replies(event) {
+ var target = event.target;
+
+ var sub_text = target.getAttribute('data-inner-text');
+ var inner_text = target.getAttribute('data-sub-text');
+
+ var body = target.parentNode.parentNode.children[1];
+ body.style.display = 'none';
+
+ target.textContent = sub_text;
+ target.onclick = show_youtube_replies;
+ target.setAttribute('data-inner-text', inner_text);
+ target.setAttribute('data-sub-text', sub_text);
+}
+
+function show_youtube_replies(event) {
+ var target = event.target;
+
+ var sub_text = target.getAttribute('data-inner-text');
+ var inner_text = target.getAttribute('data-sub-text');
+
+ var body = target.parentNode.parentNode.children[1];
+ body.style.display = '';
+
+ target.textContent = sub_text;
+ target.onclick = hide_youtube_replies;
+ target.setAttribute('data-inner-text', inner_text);
+ target.setAttribute('data-sub-text', sub_text);
+}
+
+function get_youtube_comments() {
+ var comments = document.getElementById('comments');
+
+ var fallback = comments.innerHTML;
+ comments.innerHTML = spinnerHTML;
+
+ var baseUrl = video_data.base_url || '/api/v1/comments/'+ video_data.id
+ var url = baseUrl +
+ '?format=html' +
+ '&hl=' + video_data.preferences.locale +
+ '&thin_mode=' + video_data.preferences.thin_mode;
+
+ if (video_data.ucid) {
+ url += '&ucid=' + video_data.ucid
+ }
+
+ var onNon200 = function (xhr) { comments.innerHTML = fallback; };
+ if (video_data.params.comments[1] === 'youtube')
+ onNon200 = function (xhr) {};
+
+ helpers.xhr('GET', url, {retries: 5, entity_name: 'comments'}, {
+ on200: function (response) {
+ var commentInnerHtml = ' \
+ \
+
\
+ [ − ] \
+ {commentsText} \
+
\
+
\
+ '
+ if (video_data.support_reddit) {
+ commentInnerHtml += ' \
+ {redditComments} \
+ \
+ '
+ }
+ commentInnerHtml += ' \
+
\
+ {contentHtml}
\
+
'
+ commentInnerHtml = commentInnerHtml.supplant({
+ contentHtml: response.contentHtml,
+ redditComments: video_data.reddit_comments_text,
+ commentsText: video_data.comments_text.supplant({
+ // toLocaleString correctly splits number with local thousands separator. e.g.:
+ // '1,234,567.89' for user with English locale
+ // '1 234 567,89' for user with Russian locale
+ // '1.234.567,89' for user with Portuguese locale
+ commentCount: response.commentCount.toLocaleString()
+ })
+ });
+ comments.innerHTML = commentInnerHtml;
+ comments.children[0].children[0].children[0].onclick = toggle_comments;
+ if (video_data.support_reddit) {
+ comments.children[0].children[1].children[0].onclick = swap_comments;
+ }
+ },
+ onNon200: onNon200, // declared above
+ onError: function (xhr) {
+ comments.innerHTML = spinnerHTML;
+ },
+ onTimeout: function (xhr) {
+ comments.innerHTML = spinnerHTML;
+ }
+ });
+}
+
+function get_youtube_replies(target, load_more, load_replies) {
+ var continuation = target.getAttribute('data-continuation');
+
+ var body = target.parentNode.parentNode;
+ var fallback = body.innerHTML;
+ body.innerHTML = spinnerHTML;
+ var baseUrl = video_data.base_url || '/api/v1/comments/'+ video_data.id
+ var url = baseUrl +
+ '?format=html' +
+ '&hl=' + video_data.preferences.locale +
+ '&thin_mode=' + video_data.preferences.thin_mode +
+ '&continuation=' + continuation;
+
+ if (video_data.ucid) {
+ url += '&ucid=' + video_data.ucid
+ }
+ if (load_replies) url += '&action=action_get_comment_replies';
+
+ helpers.xhr('GET', url, {}, {
+ on200: function (response) {
+ if (load_more) {
+ body = body.parentNode.parentNode;
+ body.removeChild(body.lastElementChild);
+ body.insertAdjacentHTML('beforeend', response.contentHtml);
+ } else {
+ body.removeChild(body.lastElementChild);
+
+ var p = document.createElement('p');
+ var a = document.createElement('a');
+ p.appendChild(a);
+
+ a.href = 'javascript:void(0)';
+ a.onclick = hide_youtube_replies;
+ a.setAttribute('data-sub-text', video_data.hide_replies_text);
+ a.setAttribute('data-inner-text', video_data.show_replies_text);
+ a.textContent = video_data.hide_replies_text;
+
+ var div = document.createElement('div');
+ div.innerHTML = response.contentHtml;
+
+ body.appendChild(p);
+ body.appendChild(div);
+ }
+ },
+ onNon200: function (xhr) {
+ body.innerHTML = fallback;
+ },
+ onTimeout: function (xhr) {
+ console.warn('Pulling comments failed');
+ body.innerHTML = fallback;
+ }
+ });
+}
\ No newline at end of file
diff --git a/assets/js/post.js b/assets/js/post.js
new file mode 100644
index 00000000..fcbc9155
--- /dev/null
+++ b/assets/js/post.js
@@ -0,0 +1,3 @@
+addEventListener('load', function (e) {
+ get_youtube_comments();
+});
diff --git a/assets/js/watch.js b/assets/js/watch.js
index 36506abd..26ad138f 100644
--- a/assets/js/watch.js
+++ b/assets/js/watch.js
@@ -1,14 +1,4 @@
'use strict';
-var video_data = JSON.parse(document.getElementById('video_data').textContent);
-var spinnerHTML = '
';
-var spinnerHTMLwithHR = spinnerHTML + '
';
-
-String.prototype.supplant = function (o) {
- return this.replace(/{([^{}]*)}/g, function (a, b) {
- var r = o[b];
- return typeof r === 'string' || typeof r === 'number' ? r : a;
- });
-};
function toggle_parent(target) {
var body = target.parentNode.parentNode.children[1];
@@ -21,18 +11,6 @@ function toggle_parent(target) {
}
}
-function toggle_comments(event) {
- var target = event.target;
- var body = target.parentNode.parentNode.parentNode.children[1];
- if (body.style.display === 'none') {
- target.textContent = '[ − ]';
- body.style.display = '';
- } else {
- target.textContent = '[ + ]';
- body.style.display = 'none';
- }
-}
-
function swap_comments(event) {
var source = event.target.getAttribute('data-comments');
@@ -43,36 +21,6 @@ function swap_comments(event) {
}
}
-function hide_youtube_replies(event) {
- var target = event.target;
-
- var sub_text = target.getAttribute('data-inner-text');
- var inner_text = target.getAttribute('data-sub-text');
-
- var body = target.parentNode.parentNode.children[1];
- body.style.display = 'none';
-
- target.textContent = sub_text;
- target.onclick = show_youtube_replies;
- target.setAttribute('data-inner-text', inner_text);
- target.setAttribute('data-sub-text', sub_text);
-}
-
-function show_youtube_replies(event) {
- var target = event.target;
-
- var sub_text = target.getAttribute('data-inner-text');
- var inner_text = target.getAttribute('data-sub-text');
-
- var body = target.parentNode.parentNode.children[1];
- body.style.display = '';
-
- target.textContent = sub_text;
- target.onclick = hide_youtube_replies;
- target.setAttribute('data-inner-text', inner_text);
- target.setAttribute('data-sub-text', sub_text);
-}
-
var continue_button = document.getElementById('continue');
if (continue_button) {
continue_button.onclick = continue_autoplay;
@@ -208,111 +156,6 @@ function get_reddit_comments() {
});
}
-function get_youtube_comments() {
- var comments = document.getElementById('comments');
-
- var fallback = comments.innerHTML;
- comments.innerHTML = spinnerHTML;
-
- var url = '/api/v1/comments/' + video_data.id +
- '?format=html' +
- '&hl=' + video_data.preferences.locale +
- '&thin_mode=' + video_data.preferences.thin_mode;
-
- var onNon200 = function (xhr) { comments.innerHTML = fallback; };
- if (video_data.params.comments[1] === 'youtube')
- onNon200 = function (xhr) {};
-
- helpers.xhr('GET', url, {retries: 5, entity_name: 'comments'}, {
- on200: function (response) {
- comments.innerHTML = ' \
- \
- {contentHtml}
\
-
'.supplant({
- contentHtml: response.contentHtml,
- redditComments: video_data.reddit_comments_text,
- commentsText: video_data.comments_text.supplant({
- // toLocaleString correctly splits number with local thousands separator. e.g.:
- // '1,234,567.89' for user with English locale
- // '1 234 567,89' for user with Russian locale
- // '1.234.567,89' for user with Portuguese locale
- commentCount: response.commentCount.toLocaleString()
- })
- });
-
- comments.children[0].children[0].children[0].onclick = toggle_comments;
- comments.children[0].children[1].children[0].onclick = swap_comments;
- },
- onNon200: onNon200, // declared above
- onError: function (xhr) {
- comments.innerHTML = spinnerHTML;
- },
- onTimeout: function (xhr) {
- comments.innerHTML = spinnerHTML;
- }
- });
-}
-
-function get_youtube_replies(target, load_more, load_replies) {
- var continuation = target.getAttribute('data-continuation');
-
- var body = target.parentNode.parentNode;
- var fallback = body.innerHTML;
- body.innerHTML = spinnerHTML;
-
- var url = '/api/v1/comments/' + video_data.id +
- '?format=html' +
- '&hl=' + video_data.preferences.locale +
- '&thin_mode=' + video_data.preferences.thin_mode +
- '&continuation=' + continuation;
- if (load_replies) url += '&action=action_get_comment_replies';
-
- helpers.xhr('GET', url, {}, {
- on200: function (response) {
- if (load_more) {
- body = body.parentNode.parentNode;
- body.removeChild(body.lastElementChild);
- body.insertAdjacentHTML('beforeend', response.contentHtml);
- } else {
- body.removeChild(body.lastElementChild);
-
- var p = document.createElement('p');
- var a = document.createElement('a');
- p.appendChild(a);
-
- a.href = 'javascript:void(0)';
- a.onclick = hide_youtube_replies;
- a.setAttribute('data-sub-text', video_data.hide_replies_text);
- a.setAttribute('data-inner-text', video_data.show_replies_text);
- a.textContent = video_data.hide_replies_text;
-
- var div = document.createElement('div');
- div.innerHTML = response.contentHtml;
-
- body.appendChild(p);
- body.appendChild(div);
- }
- },
- onNon200: function (xhr) {
- body.innerHTML = fallback;
- },
- onTimeout: function (xhr) {
- console.warn('Pulling comments failed');
- body.innerHTML = fallback;
- }
- });
-}
-
if (video_data.play_next) {
player.on('ended', function () {
var url = new URL('https://example.com/watch?v=' + video_data.next_video);
diff --git a/src/invidious/channels/community.cr b/src/invidious/channels/community.cr
index 791f1641..85ddff35 100644
--- a/src/invidious/channels/community.cr
+++ b/src/invidious/channels/community.cr
@@ -24,7 +24,35 @@ def fetch_channel_community(ucid, cursor, locale, format, thin_mode)
return extract_channel_community(items, ucid: ucid, locale: locale, format: format, thin_mode: thin_mode)
end
-def extract_channel_community(items, *, ucid, locale, format, thin_mode)
+def fetch_channel_community_post(ucid, postId, locale, format, thin_mode, params : String | Nil = nil)
+ if params.nil?
+ object = {
+ "2:string" => "community",
+ "25:embedded" => {
+ "22:string" => postId.to_s,
+ },
+ "45:embedded" => {
+ "2:varint" => 1_i64,
+ "3:varint" => 1_i64,
+ },
+ }
+ params = object.try { |i| Protodec::Any.cast_json(i) }
+ .try { |i| Protodec::Any.from_json(i) }
+ .try { |i| Base64.urlsafe_encode(i) }
+ .try { |i| URI.encode_www_form(i) }
+ end
+
+ initial_data = YoutubeAPI.browse(ucid, params: params)
+
+ items = [] of JSON::Any
+ extract_items(initial_data) do |item|
+ items << item
+ end
+
+ return extract_channel_community(items, ucid: ucid, locale: locale, format: format, thin_mode: thin_mode, is_single_post: true)
+end
+
+def extract_channel_community(items, *, ucid, locale, format, thin_mode, is_single_post : Bool = false)
if message = items[0]["messageRenderer"]?
error_message = (message["text"]["simpleText"]? ||
message["text"]["runs"]?.try &.[0]?.try &.["text"]?)
@@ -39,6 +67,9 @@ def extract_channel_community(items, *, ucid, locale, format, thin_mode)
response = JSON.build do |json|
json.object do
json.field "authorId", ucid
+ if is_single_post
+ json.field "singlePost", true
+ end
json.field "comments" do
json.array do
items.each do |post|
@@ -240,8 +271,10 @@ def extract_channel_community(items, *, ucid, locale, format, thin_mode)
end
end
end
- if cont = items.dig?(-1, "continuationItemRenderer", "continuationEndpoint", "continuationCommand", "token")
- json.field "continuation", extract_channel_community_cursor(cont.as_s)
+ if !is_single_post
+ if cont = items.dig?(-1, "continuationItemRenderer", "continuationEndpoint", "continuationCommand", "token")
+ json.field "continuation", extract_channel_community_cursor(cont.as_s)
+ end
end
end
end
diff --git a/src/invidious/comments/youtube.cr b/src/invidious/comments/youtube.cr
index 1ba1b534..da7f0543 100644
--- a/src/invidious/comments/youtube.cr
+++ b/src/invidious/comments/youtube.cr
@@ -13,6 +13,51 @@ module Invidious::Comments
client_config = YoutubeAPI::ClientConfig.new(region: region)
response = YoutubeAPI.next(continuation: ctoken, client_config: client_config)
+ return parse_youtube(id, response, format, locale, thin_mode, sort_by)
+ end
+
+ def fetch_community_post_comments(ucid, postId)
+ object = {
+ "2:string" => "community",
+ "25:embedded" => {
+ "22:string" => postId,
+ },
+ "45:embedded" => {
+ "2:varint" => 1_i64,
+ "3:varint" => 1_i64,
+ },
+ "53:embedded" => {
+ "4:embedded" => {
+ "6:varint" => 0_i64,
+ "27:varint" => 1_i64,
+ "29:string" => postId,
+ "30:string" => ucid,
+ },
+ "8:string" => "comments-section",
+ },
+ }
+
+ objectParsed = object.try { |i| Protodec::Any.cast_json(i) }
+ .try { |i| Protodec::Any.from_json(i) }
+ .try { |i| Base64.urlsafe_encode(i) }
+
+ object2 = {
+ "80226972:embedded" => {
+ "2:string" => ucid,
+ "3:string" => objectParsed,
+ },
+ }
+
+ continuation = object2.try { |i| Protodec::Any.cast_json(i) }
+ .try { |i| Protodec::Any.from_json(i) }
+ .try { |i| Base64.urlsafe_encode(i) }
+ .try { |i| URI.encode_www_form(i) }
+
+ initial_data = YoutubeAPI.browse(continuation: continuation)
+ return initial_data
+ end
+
+ def parse_youtube(id, response, format, locale, thin_mode, sort_by = "top", isPost = false)
contents = nil
if on_response_received_endpoints = response["onResponseReceivedEndpoints"]?
@@ -68,7 +113,11 @@ module Invidious::Comments
json.field "commentCount", comment_count
end
- json.field "videoId", id
+ if isPost
+ json.field "postId", id
+ else
+ json.field "videoId", id
+ end
json.field "comments" do
json.array do
diff --git a/src/invidious/frontend/comments_youtube.cr b/src/invidious/frontend/comments_youtube.cr
index 41f43f04..ecc0bc1b 100644
--- a/src/invidious/frontend/comments_youtube.cr
+++ b/src/invidious/frontend/comments_youtube.cr
@@ -23,6 +23,24 @@ module Invidious::Frontend::Comments