Compare commits

...

16 Commits

Author SHA1 Message Date
Samantaz Fox
e238c08be5
Search: Populate search bar with ChannelId (#3805) 2023-05-23 21:57:07 +02:00
Samantaz Fox
8d434ac06a
User: Allow CSV Youtube playlists to be imported (#3595) 2023-05-23 19:34:24 +02:00
Samantaz Fox
1333e6db26
API: Add hashtag endpoint (#3692) 2023-05-23 19:31:19 +02:00
ChunkyProgrammer
8bd2e60abc
Use string interpolation instead of concatenation
Co-authored-by: Samantaz Fox <coding@samantaz.fr>
2023-05-22 09:19:32 -04:00
chunky programmer
12b4dd9191 Populate search bar with ChannelId 2023-05-14 17:25:32 -04:00
chunky programmer
d728599251 add page parameter 2023-05-14 15:58:15 -04:00
ChunkyProgrammer
d6fb5c03b7 add hashtag endpoint 2023-05-14 15:58:14 -04:00
Gavin
c421f1f205
Merge branch 'iv-org:master' into youtube-playlist-import 2023-04-03 17:09:34 -07:00
thtmnisamnstr
fffdaa1410 Updated csv reading as per feedback and ran
Signed-off-by: thtmnisamnstr <gavinj1984@gmail.com>
2023-04-03 17:07:58 -07:00
thtmnisamnstr
3341929060 removed unnecessary conditionals and uninitialized variable declarations
Signed-off-by: thtmnisamnstr <gavinj1984@gmail.com>
2023-03-07 15:46:36 -08:00
thtmnisamnstr
b3eea6ab3e improved import algorithm, fixed a referer issue from the playlists page after deleting a playlist
Signed-off-by: thtmnisamnstr <gavinj1984@gmail.com>
2023-02-23 15:55:38 -08:00
thtmnisamnstr
6f01d6eacf ran crystal tool format. it should fix some CI issues
Signed-off-by: thtmnisamnstr <gavinj1984@gmail.com>
2023-02-10 12:00:02 -08:00
Gavin Johnson
72d0c9e409 removed comments
Signed-off-by: Gavin Johnson <gavinj1984@gmail.com>
2023-01-28 09:57:28 -08:00
Gavin Johnson
5c7bda66ae removed comments
Signed-off-by: Gavin Johnson <gavinj1984@gmail.com>
2023-01-28 09:55:36 -08:00
Gavin Johnson
96344f28b4 added youtube playlist import functionality. fixes issue #2114
Signed-off-by: Gavin Johnson <gavinj1984@gmail.com>
2023-01-28 09:26:16 -08:00
Gavin Johnson
855202e40e added youtube playlist import; initial commit
Signed-off-by: Gavin Johnson <gavinj1984@gmail.com>
2023-01-16 15:40:38 -08:00
9 changed files with 131 additions and 6 deletions

View File

@ -33,6 +33,7 @@
"Import": "Import",
"Import Invidious data": "Import Invidious JSON data",
"Import YouTube subscriptions": "Import YouTube/OPML subscriptions",
"Import YouTube playlist (.csv)": "Import YouTube playlist (.csv)",
"Import FreeTube subscriptions (.db)": "Import FreeTube subscriptions (.db)",
"Import NewPipe subscriptions (.json)": "Import NewPipe subscriptions (.json)",
"Import NewPipe data (.zip)": "Import NewPipe data (.zip)",

View File

@ -55,4 +55,32 @@ module Invidious::Routes::API::V1::Search
return error_json(500, ex)
end
end
def self.hashtag(env)
hashtag = env.params.url["hashtag"]
page = env.params.query["page"]?.try &.to_i? || 1
locale = env.get("preferences").as(Preferences).locale
region = env.params.query["region"]?
env.response.content_type = "application/json"
begin
results = Invidious::Hashtag.fetch(hashtag, page, region)
rescue ex
return error_json(400, ex)
end
JSON.build do |json|
json.object do
json.field "results" do
json.array do
results.each do |item|
item.to_json(locale, json)
end
end
end
end
end
end
end

View File

@ -278,6 +278,7 @@ module Invidious::Routes::Channels
return error_template(500, ex)
end
env.set "search", "channel:#{ucid} "
return {locale, user, subscriptions, continuation, ucid, channel}
end
end

View File

@ -310,6 +310,15 @@ module Invidious::Routes::PreferencesRoute
response: error_template(415, "Invalid subscription file uploaded")
)
end
when "import_youtube_pl"
filename = part.filename || ""
success = Invidious::User::Import.from_youtube_pl(user, body, filename, type)
if !success
haltf(env, status_code: 415,
response: error_template(415, "Invalid playlist file uploaded")
)
end
when "import_freetube"
Invidious::User::Import.from_freetube(user, body)
when "import_newpipe_subscriptions"

View File

@ -65,7 +65,11 @@ module Invidious::Routes::Search
redirect_url = Invidious::Frontend::Misc.redirect_url(env)
env.set "search", query.text
if query.type == Invidious::Search::Query::Type::Channel
env.set "search", "channel:#{query.channel} #{query.text}"
else
env.set "search", query.text
end
templated "search"
end
end

View File

@ -243,6 +243,7 @@ module Invidious::Routing
# Search
get "/api/v1/search", {{namespace}}::Search, :search
get "/api/v1/search/suggestions", {{namespace}}::Search, :search_suggestions
get "/api/v1/hashtag/:hashtag", {{namespace}}::Search, :hashtag
# Authenticated

View File

@ -30,6 +30,60 @@ struct Invidious::User
return subscriptions
end
def parse_playlist_export_csv(user : User, raw_input : String)
# Split the input into head and body content
raw_head, raw_body = raw_input.split("\n\n", limit: 2, remove_empty: true)
# Create the playlist from the head content
csv_head = CSV.new(raw_head, headers: true)
csv_head.next
title = csv_head[4]
description = csv_head[5]
visibility = csv_head[6]
if visibility.compare("Public", case_insensitive: true) == 0
privacy = PlaylistPrivacy::Public
else
privacy = PlaylistPrivacy::Private
end
playlist = create_playlist(title, privacy, user)
Invidious::Database::Playlists.update_description(playlist.id, description)
# Add each video to the playlist from the body content
csv_body = CSV.new(raw_body, headers: true)
csv_body.each do |row|
video_id = row[0]
if playlist
next if !video_id
next if video_id == "Video Id"
begin
video = get_video(video_id)
rescue ex
next
end
playlist_video = PlaylistVideo.new({
title: video.title,
id: video.id,
author: video.author,
ucid: video.ucid,
length_seconds: video.length_seconds,
published: video.published,
plid: playlist.id,
live_now: video.live_now,
index: Random::Secure.rand(0_i64..Int64::MAX),
})
Invidious::Database::PlaylistVideos.insert(playlist_video)
Invidious::Database::Playlists.update_video_added(playlist.id, playlist_video.index)
end
end
return playlist
end
# -------------------
# Invidious
# -------------------
@ -149,6 +203,21 @@ struct Invidious::User
return true
end
def from_youtube_pl(user : User, body : String, filename : String, type : String) : Bool
extension = filename.split(".").last
if extension == "csv" || type == "text/csv"
playlist = parse_playlist_export_csv(user, body)
if playlist
return true
else
return false
end
else
return false
end
end
# -------------------
# Freetube
# -------------------

View File

@ -5,12 +5,19 @@
<%= rendered "components/feed_menu" %>
<div class="pure-g h-box">
<div class="pure-u-2-3">
<div class="pure-u-1-3">
<h3><%= translate(locale, "user_created_playlists", %(<span id="count">#{items_created.size}</span>)) %></h3>
</div>
<div class="pure-u-1-3" style="text-align:right">
<h3>
<a href="/create_playlist?referer=<%= URI.encode_www_form(referer) %>"><%= translate(locale, "Create playlist") %></a>
<div class="pure-u-1-3">
<h3 style="text-align:center">
<a href="/create_playlist?referer=<%= URI.encode_www_form("/feed/playlists") %>"><%= translate(locale, "Create playlist") %></a>
</h3>
</div>
<div class="pure-u-1-3">
<h3 style="text-align:right">
<a href="/data_control?referer=<%= URI.encode_www_form("/feed/playlists") %>">
<%= translate(locale, "Import/export") %>
</a>
</h3>
</div>
</div>

View File

@ -8,7 +8,7 @@
<legend><%= translate(locale, "Import") %></legend>
<div class="pure-control-group">
<label for="import_youtube"><%= translate(locale, "Import Invidious data") %></label>
<label for="import_invidious"><%= translate(locale, "Import Invidious data") %></label>
<input type="file" id="import_invidious" name="import_invidious">
</div>
@ -21,6 +21,11 @@
<input type="file" id="import_youtube" name="import_youtube">
</div>
<div class="pure-control-group">
<label for="import_youtube_pl"><%= translate(locale, "Import YouTube playlist (.csv)") %></label>
<input type="file" id="import_youtube_pl" name="import_youtube_pl">
</div>
<div class="pure-control-group">
<label for="import_freetube"><%= translate(locale, "Import FreeTube subscriptions (.db)") %></label>
<input type="file" id="import_freetube" name="import_freetube">