diff --git a/locales/en-US.json b/locales/en-US.json index 4f2c2770..e7867f8b 100644 --- a/locales/en-US.json +++ b/locales/en-US.json @@ -501,5 +501,6 @@ "toggle_theme": "Toggle Theme", "carousel_slide": "Slide {{current}} of {{total}}", "carousel_skip": "Skip the Carousel", - "carousel_go_to": "Go to slide `x`" + "carousel_go_to": "Go to slide `x`", + "confirm_dialog_external_link": "You are leaving Invidious. Continue to external link?" } diff --git a/src/invidious/channels/about.cr b/src/invidious/channels/about.cr index 13909527..a6495383 100644 --- a/src/invidious/channels/about.cr +++ b/src/invidious/channels/about.cr @@ -159,6 +159,9 @@ def get_about_info(ucid, locale) : AboutChannel end end + # use comments link_utils to replace external links with the confirmation page + description_html = Invidious::Comments.replace_external_links(description_html) + sub_count = 0 if (metadata_rows = initdata.dig?("header", "pageHeaderRenderer", "content", "pageHeaderViewModel", "metadata", "contentMetadataViewModel", "metadataRows").try &.as_a) diff --git a/src/invidious/comments/links_util.cr b/src/invidious/comments/links_util.cr index f89b86d3..a28db740 100644 --- a/src/invidious/comments/links_util.cr +++ b/src/invidious/comments/links_util.cr @@ -73,4 +73,30 @@ module Invidious::Comments return html.to_xml(options: XML::SaveOptions::NO_DECL) end + + def replace_external_links(html) + # Check if the document is empty + # Prevents edge-case bug with Reddit comments, see issue #3115 + if html.nil? || html.empty? + return html + end + + html = XML.parse_html(html) + + html.xpath_nodes(%q(//a)).each do |anchor| + url = URI.parse(anchor["href"]) + + if !url.host.nil? && !url.host.not_nil!.ends_with?("youtube.com") && !url.host.not_nil!.ends_with?("youtu.be") + confirm_leave = "/confirm_leave?link=#{URI.encode_path(url.to_s)}" + anchor["href"] = confirm_leave + end + end + + html = html.xpath_node(%q(//body)).not_nil! + if node = html.xpath_node(%q(./p)) + html = node + end + + return html.to_xml(options: XML::SaveOptions::NO_DECL) + end end diff --git a/src/invidious/comments/youtube.cr b/src/invidious/comments/youtube.cr index 0716fcde..148f6cbe 100644 --- a/src/invidious/comments/youtube.cr +++ b/src/invidious/comments/youtube.cr @@ -303,6 +303,7 @@ module Invidious::Comments if format == "html" response = JSON.parse(response) content_html = Frontend::Comments.template_youtube(response, locale, thin_mode) + content_html = Comments.replace_external_links(content_html) response = JSON.build do |json| json.object do json.field "contentHtml", content_html diff --git a/src/invidious/frontend/comments_youtube.cr b/src/invidious/frontend/comments_youtube.cr index a0e1d783..5e9faece 100644 --- a/src/invidious/frontend/comments_youtube.cr +++ b/src/invidious/frontend/comments_youtube.cr @@ -1,3 +1,5 @@ +require "uri" + module Invidious::Frontend::Comments extend self @@ -148,13 +150,17 @@ module Invidious::Frontend::Comments END_HTML if comments["videoId"]? + permalink = "https://www.youtube.com/watch?v=#{comments["videoId"]}&lc=#{child["commentId"]}" + permalink_confirm = "/confirm_leave?link=#{URI.encode_path(permalink)}" html << <<-END_HTML - [YT] + [YT] | END_HTML elsif comments["authorId"]? + permalink = "https://www.youtube.com/channel/#{comments["authorId"]}/community?lb=#{child["commentId"]}" + permalink_confirm = "/confirm_leave?link=#{URI.encode_path(permalink)}" html << <<-END_HTML - [YT] + [YT] | END_HTML end diff --git a/src/invidious/helpers/errors.cr b/src/invidious/helpers/errors.cr index 900cb0c6..fbc26af5 100644 --- a/src/invidious/helpers/errors.cr +++ b/src/invidious/helpers/errors.cr @@ -182,6 +182,9 @@ def error_redirect_helper(env : HTTP::Server::Context) go_to_youtube = translate(locale, "next_steps_error_message_go_to_youtube") switch_instance = translate(locale, "Switch Invidious Instance") + youtube_link = "https://youtube.com#{env.request.resource}" + youtube_link_confirm = "/confirm_leave?link=#{URI.encode_path(youtube_link)}" + return <<-END_HTML
#{next_steps_text}