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 aecac87f..8037c243 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,8 +150,10 @@ 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"]? diff --git a/src/invidious/routes/misc.cr b/src/invidious/routes/misc.cr index d6bd9571..28a134a9 100644 --- a/src/invidious/routes/misc.cr +++ b/src/invidious/routes/misc.cr @@ -43,4 +43,14 @@ module Invidious::Routes::Misc instance_url = fetch_random_instance env.redirect "https://#{instance_url}#{referer}" end + + def self.confirm_leave(env) + locale = env.get("preferences").as(Preferences).locale + + link = env.params.query["link"]? + + referer = get_referer(env) + + templated "confirm_leave" + end end diff --git a/src/invidious/routing.cr b/src/invidious/routing.cr index ba05da19..1504e7ea 100644 --- a/src/invidious/routing.cr +++ b/src/invidious/routing.cr @@ -21,6 +21,7 @@ module Invidious::Routing get "/privacy", Routes::Misc, :privacy get "/licenses", Routes::Misc, :licenses get "/redirect", Routes::Misc, :cross_instance_redirect + get "/confirm_leave", Routes::Misc, :confirm_leave self.register_channel_routes self.register_watch_routes diff --git a/src/invidious/videos/parser.cr b/src/invidious/videos/parser.cr index 4bdb2512..2990b4a5 100644 --- a/src/invidious/videos/parser.cr +++ b/src/invidious/videos/parser.cr @@ -311,6 +311,9 @@ def parse_video_info(video_id : String, player_response : Hash(String, JSON::Any description_html = parse_description(video_secondary_renderer.try &.dig?("attributedDescription"), video_id) + # use comments link_utils to replace external links with the confirmation page + description_html = Invidious::Comments.replace_external_links(description_html) + # Video metadata metadata = video_secondary_renderer diff --git a/src/invidious/views/confirm_leave.ecr b/src/invidious/views/confirm_leave.ecr new file mode 100644 index 00000000..a46cb187 --- /dev/null +++ b/src/invidious/views/confirm_leave.ecr @@ -0,0 +1,22 @@ +<% content_for "header" do %> +<%= translate(locale, "Leave") %> - Invidious +<% end %> + +
+

<%= translate(locale, "You are leaving Invidious. Continue to external link?") %>

+ +

<%= link %>

+ +
+ + +
+
diff --git a/src/invidious/views/watch.ecr b/src/invidious/views/watch.ecr index 9e7467dd..70c43a2d 100644 --- a/src/invidious/views/watch.ecr +++ b/src/invidious/views/watch.ecr @@ -122,9 +122,12 @@ we're going to need to do it here in order to allow for translations. link_yt_watch = IV::HttpServer::Utils.add_params_to_url(link_yt_watch, link_yt_param) link_yt_embed = IV::HttpServer::Utils.add_params_to_url(link_yt_embed, link_yt_param) end + + confirm_yt_watch = "/confirm_leave?link=#{URI.encode_path(link_yt_watch.to_s)}" + confirm_yt_embed = "/confirm_leave?link=#{URI.encode_path(link_yt_embed.to_s)}" -%> - <%= translate(locale, "videoinfo_watch_on_youTube") %> - (<%= translate(locale, "videoinfo_youTube_embed_link") %>) + <%= translate(locale, "videoinfo_watch_on_youTube") %> + (<%= translate(locale, "videoinfo_youTube_embed_link") %>)