diff --git a/patches/8-2545.patch b/patches/8-2545.patch new file mode 100644 index 0000000..c0d6a9d --- /dev/null +++ b/patches/8-2545.patch @@ -0,0 +1,179 @@ +From 3b9e7e0edfb8d371398a5830ccace74837fa984b Mon Sep 17 00:00:00 2001 +From: bbielsa +Date: Tue, 26 Oct 2021 21:19:20 -0400 +Subject: [PATCH 1/4] Add helper function parse_subscription_export_csv() which + parses the csv format returned by the subscription exporter + +--- + src/invidious/helpers/utils.cr | 21 +++++++++++++++++++++ + 1 file changed, 21 insertions(+) + +diff --git a/src/invidious/helpers/utils.cr b/src/invidious/helpers/utils.cr +index 603b4e1f3..05f368792 100644 +--- a/src/invidious/helpers/utils.cr ++++ b/src/invidious/helpers/utils.cr +@@ -1,4 +1,5 @@ + require "db" ++require "csv" + + # See http://www.evanmiller.org/how-not-to-sort-by-average-rating.html + def ci_lower_bound(pos, n) +@@ -362,3 +363,23 @@ def fetch_random_instance + + return filtered_instance_list.sample(1)[0] + end ++ ++def parse_subscription_export_csv(csv_content : String) ++ rows = CSV.new(csv_content, headers: true) ++ subscriptions = Array(String).new ++ ++ rows.each do |row| ++ # Channel ID is the first column in the csv export we can't use the header ++ # name, because I believe the header name is localized depending on the ++ # language the user has set on their account ++ channel_id = row[0].strip ++ ++ if channel_id.empty? ++ next ++ end ++ ++ subscriptions << channel_id ++ end ++ ++ subscriptions ++end + +From 9b99b74450b52481ca85e87afd4d76a0a3ed2508 Mon Sep 17 00:00:00 2001 +From: bbielsa +Date: Wed, 27 Oct 2021 17:54:40 -0400 +Subject: [PATCH 2/4] Test if body content is likely JSON, if so parse the json + format of subscriptions export. If the content is anything else, assume it is + CSV and parse + +--- + src/invidious.cr | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/src/invidious.cr b/src/invidious.cr +index 21a12ff2e..4bb493a8a 100644 +--- a/src/invidious.cr ++++ b/src/invidious.cr +@@ -829,11 +829,14 @@ post "/data_control" do |env| + user.subscriptions += subscriptions.xpath_nodes(%q(//outline[@type="rss"])).map do |channel| + channel["xmlUrl"].match(/UC[a-zA-Z0-9_-]{22}/).not_nil![0] + end +- else ++ elsif body[0] == '[' + subscriptions = JSON.parse(body) + user.subscriptions += subscriptions.as_a.compact_map do |entry| + entry["snippet"]["resourceId"]["channelId"].as_s + end ++ else ++ subscriptions = parse_subscription_export_csv(body) ++ user.subscriptions += subscriptions + end + user.subscriptions.uniq! + + +From 3ff47c8cb9560fb2d7f242cb96f29e44bece5618 Mon Sep 17 00:00:00 2001 +From: bbielsa +Date: Wed, 3 Nov 2021 00:31:43 -0400 +Subject: [PATCH 3/4] Move parse_subscription_export_csv function to + user/imports.cr + +--- + src/invidious/helpers/utils.cr | 20 -------------------- + src/invidious/user/imports.cr | 17 +++++++++++++++++ + 2 files changed, 17 insertions(+), 20 deletions(-) + create mode 100644 src/invidious/user/imports.cr + +diff --git a/src/invidious/helpers/utils.cr b/src/invidious/helpers/utils.cr +index 05f368792..3bd87a87e 100644 +--- a/src/invidious/helpers/utils.cr ++++ b/src/invidious/helpers/utils.cr +@@ -363,23 +363,3 @@ def fetch_random_instance + + return filtered_instance_list.sample(1)[0] + end +- +-def parse_subscription_export_csv(csv_content : String) +- rows = CSV.new(csv_content, headers: true) +- subscriptions = Array(String).new +- +- rows.each do |row| +- # Channel ID is the first column in the csv export we can't use the header +- # name, because I believe the header name is localized depending on the +- # language the user has set on their account +- channel_id = row[0].strip +- +- if channel_id.empty? +- next +- end +- +- subscriptions << channel_id +- end +- +- subscriptions +-end +diff --git a/src/invidious/user/imports.cr b/src/invidious/user/imports.cr +new file mode 100644 +index 000000000..0ea554bd0 +--- /dev/null ++++ b/src/invidious/user/imports.cr +@@ -0,0 +1,17 @@ ++def parse_subscription_export_csv(csv_content : String) ++ rows = CSV.new(csv_content, headers: true) ++ subscriptions = Array(String).new ++ ++ rows.each do |row| ++ # Channel ID is the first column in the csv export we can't use the header ++ # name, because the header name is localized depending on the ++ # language the user has set on their account ++ channel_id = row[0].strip ++ ++ next if channel_id.empty? ++ ++ subscriptions << channel_id ++ end ++ ++ subscriptions ++end + +From 0e138d64efe86cec4e9d70ddc0f49747fdc44a35 Mon Sep 17 00:00:00 2001 +From: bbielsa +Date: Wed, 3 Nov 2021 00:45:03 -0400 +Subject: [PATCH 4/4] Detect the type of subscription import format based on + the content type of the file uploaded + +--- + src/invidious.cr | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/src/invidious.cr b/src/invidious.cr +index 4bb493a8a..91403ba96 100644 +--- a/src/invidious.cr ++++ b/src/invidious.cr +@@ -751,6 +751,8 @@ post "/data_control" do |env| + + HTTP::FormData.parse(env.request) do |part| + body = part.body.gets_to_end ++ type = part.headers["Content-Type"] ++ + next if body.empty? + + # TODO: Unify into single import based on content-type +@@ -824,12 +826,12 @@ post "/data_control" do |env| + end + end + when "import_youtube" +- if body[0..4] == "