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 d07d6cf44..bffc7ad3b 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 a768328a6..bf297a439 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 bffc7ad3b..8eae54f46 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 5500672fc..d744712d3 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 f6b3aaa69..8c38aaed5 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 96903fc7e..f94a943aa 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 f94a943aa..2c115f13a 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 2c115f13a..1ca0dc96a 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 13bbf34c3..c2756fcc4 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 a945da589..a7e218a27 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 8eae54f46..bed028750 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 c94ed9d82..ec0372402 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 c31b24e5d..69fe8d5f6 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 000000000..00a8cae94
--- /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 000000000..fcbc9155c
--- /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 36506abda..26ad138f5 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 791f16415..85ddff355 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 1ba1b534c..da7f0543e 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 41f43f044..ecc0bc1ba 100644
--- a/src/invidious/frontend/comments_youtube.cr
+++ b/src/invidious/frontend/comments_youtube.cr
@@ -23,6 +23,24 @@ module Invidious::Frontend::Comments