mirror of
https://github.com/iv-org/invidious.git
synced 2025-08-02 02:38:30 +00:00
Merge remote-tracking branch 'upstream/master' into side-menu
This commit is contained in:
commit
74d9bd30d0
@ -322,13 +322,6 @@ img.thumbnail {
|
|||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
}
|
}
|
||||||
|
|
||||||
#player {
|
|
||||||
position: absolute;
|
|
||||||
left: 0;
|
|
||||||
top: 0;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.player-dimensions.vjs-fluid {
|
.player-dimensions.vjs-fluid {
|
||||||
padding-top: 82vh;
|
padding-top: 82vh;
|
||||||
}
|
}
|
||||||
@ -336,8 +329,6 @@ img.thumbnail {
|
|||||||
#player-container {
|
#player-container {
|
||||||
position: relative;
|
position: relative;
|
||||||
padding-bottom: 82vh;
|
padding-bottom: 82vh;
|
||||||
margin-left: 1em;
|
|
||||||
margin-right: 1em;
|
|
||||||
height: 0;
|
height: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -982,12 +982,11 @@ post "/login" do |env|
|
|||||||
preferences = env.get("preferences").as(Preferences)
|
preferences = env.get("preferences").as(Preferences)
|
||||||
PG_DB.exec("UPDATE users SET preferences = $1 WHERE email = $2", preferences, user.email)
|
PG_DB.exec("UPDATE users SET preferences = $1 WHERE email = $2", preferences, user.email)
|
||||||
|
|
||||||
login.cookies["PREFS"] = HTTP::Cookie.new(name: "PREFS", value: "", expires: Time.new(1990, 1, 1),
|
cookie = env.request.cookies["PREFS"]
|
||||||
secure: secure, http_only: true)
|
cookie.expires = Time.new(1990, 1, 1)
|
||||||
|
env.response.cookies << cookie
|
||||||
end
|
end
|
||||||
|
|
||||||
login.cookies.add_response_headers(env.response.headers)
|
|
||||||
|
|
||||||
env.redirect referer
|
env.redirect referer
|
||||||
rescue ex
|
rescue ex
|
||||||
error_message = translate(locale, "Login failed. This may be because two-factor authentication is not enabled on your account.")
|
error_message = translate(locale, "Login failed. This may be because two-factor authentication is not enabled on your account.")
|
||||||
@ -1099,8 +1098,9 @@ post "/login" do |env|
|
|||||||
|
|
||||||
# Since this user has already registered, we don't want to overwrite their preferences
|
# Since this user has already registered, we don't want to overwrite their preferences
|
||||||
if env.request.cookies["PREFS"]?
|
if env.request.cookies["PREFS"]?
|
||||||
env.response.cookies["PREFS"] = HTTP::Cookie.new(name: "PREFS", value: "", expires: Time.new(1990, 1, 1),
|
cookie = env.request.cookies["PREFS"]
|
||||||
secure: secure, http_only: true)
|
cookie.expires = Time.new(1990, 1, 1)
|
||||||
|
env.response.cookies << cookie
|
||||||
end
|
end
|
||||||
elsif action == "register"
|
elsif action == "register"
|
||||||
if !config.registration_enabled
|
if !config.registration_enabled
|
||||||
@ -1156,11 +1156,12 @@ post "/login" do |env|
|
|||||||
end
|
end
|
||||||
|
|
||||||
if env.request.cookies["PREFS"]?
|
if env.request.cookies["PREFS"]?
|
||||||
preferences = env.get("preferences").as(Preferences)
|
preferences = env.get("preferences").as(Preferences).to_json
|
||||||
PG_DB.exec("UPDATE users SET preferences = $1 WHERE email = $2", preferences, user.email)
|
PG_DB.exec("UPDATE users SET preferences = $1 WHERE email = $2", preferences, user.email)
|
||||||
|
|
||||||
env.response.cookies["PREFS"] = HTTP::Cookie.new(name: "PREFS", value: "", expires: Time.new(1990, 1, 1),
|
cookie = env.request.cookies["PREFS"]
|
||||||
secure: secure, http_only: true)
|
cookie.expires = Time.new(1990, 1, 1)
|
||||||
|
env.response.cookies << cookie
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -1193,9 +1194,8 @@ get "/signout" do |env|
|
|||||||
|
|
||||||
env.request.cookies.each do |cookie|
|
env.request.cookies.each do |cookie|
|
||||||
cookie.expires = Time.new(1990, 1, 1)
|
cookie.expires = Time.new(1990, 1, 1)
|
||||||
|
env.response.cookies << cookie
|
||||||
end
|
end
|
||||||
|
|
||||||
env.request.cookies.add_response_headers(env.response.headers)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
env.redirect referer
|
env.redirect referer
|
||||||
@ -1803,8 +1803,8 @@ post "/delete_account" do |env|
|
|||||||
|
|
||||||
env.request.cookies.each do |cookie|
|
env.request.cookies.each do |cookie|
|
||||||
cookie.expires = Time.new(1990, 1, 1)
|
cookie.expires = Time.new(1990, 1, 1)
|
||||||
|
env.response.cookies << cookie
|
||||||
end
|
end
|
||||||
env.request.cookies.add_response_headers(env.response.headers)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
env.redirect referer
|
env.redirect referer
|
||||||
@ -2471,7 +2471,14 @@ get "/channel/:ucid" do |env|
|
|||||||
sort_by ||= "last"
|
sort_by ||= "last"
|
||||||
|
|
||||||
items, continuation = fetch_channel_playlists(ucid, author, auto_generated, continuation, sort_by)
|
items, continuation = fetch_channel_playlists(ucid, author, auto_generated, continuation, sort_by)
|
||||||
items.select! { |item| item.is_a?(SearchPlaylist) && !item.videos.empty? }
|
items.uniq! do |item|
|
||||||
|
if item.responds_to?(:title)
|
||||||
|
item.title
|
||||||
|
elsif item.responds_to?(:author)
|
||||||
|
item.author
|
||||||
|
end
|
||||||
|
end
|
||||||
|
items.select! { |item| item.responds_to?(:thumbnail_id) && item.thumbnail_id }
|
||||||
items = items.map { |item| item.as(SearchPlaylist) }
|
items = items.map { |item| item.as(SearchPlaylist) }
|
||||||
items.each { |item| item.author = "" }
|
items.each { |item| item.author = "" }
|
||||||
else
|
else
|
||||||
|
@ -232,13 +232,22 @@ def extract_items(nodeset, ucid = nil, author_name = nil)
|
|||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
playlist_thumbnail = node.xpath_node(%q(.//div/span/img)).try &.["data-thumb"]?
|
||||||
|
playlist_thumbnail ||= node.xpath_node(%q(.//div/span/img)).try &.["src"]
|
||||||
|
if !playlist_thumbnail || playlist_thumbnail.empty?
|
||||||
|
thumbnail_id = videos[0]?.try &.id
|
||||||
|
else
|
||||||
|
thumbnail_id = playlist_thumbnail.match(/\/vi\/(?<video_id>[a-zA-Z0-9_-]{11})\/\w+\.jpg/).try &.["video_id"]
|
||||||
|
end
|
||||||
|
|
||||||
items << SearchPlaylist.new(
|
items << SearchPlaylist.new(
|
||||||
title,
|
title,
|
||||||
plid,
|
plid,
|
||||||
author,
|
author,
|
||||||
author_id,
|
author_id,
|
||||||
video_count,
|
video_count,
|
||||||
videos
|
videos,
|
||||||
|
thumbnail_id
|
||||||
)
|
)
|
||||||
when .includes? "yt-lockup-channel"
|
when .includes? "yt-lockup-channel"
|
||||||
author = title.strip
|
author = title.strip
|
||||||
@ -399,13 +408,28 @@ def extract_shelf_items(nodeset, ucid = nil, author_name = nil)
|
|||||||
playlist_title ||= ""
|
playlist_title ||= ""
|
||||||
plid ||= ""
|
plid ||= ""
|
||||||
|
|
||||||
|
playlist_thumbnail = child_node.xpath_node(%q(.//span/img)).try &.["data-thumb"]?
|
||||||
|
playlist_thumbnail ||= child_node.xpath_node(%q(.//span/img)).try &.["src"]
|
||||||
|
if !playlist_thumbnail || playlist_thumbnail.empty?
|
||||||
|
thumbnail_id = videos[0]?.try &.id
|
||||||
|
else
|
||||||
|
thumbnail_id = playlist_thumbnail.match(/\/vi\/(?<video_id>[a-zA-Z0-9_-]{11})\/\w+\.jpg/).try &.["video_id"]
|
||||||
|
end
|
||||||
|
|
||||||
|
video_count_label = child_node.xpath_node(%q(.//span[@class="formatted-video-count-label"]))
|
||||||
|
if video_count_label
|
||||||
|
video_count = video_count_label.content.strip.match(/^\d+/).try &.[0].to_i?
|
||||||
|
end
|
||||||
|
video_count ||= 50
|
||||||
|
|
||||||
items << SearchPlaylist.new(
|
items << SearchPlaylist.new(
|
||||||
playlist_title,
|
playlist_title,
|
||||||
plid,
|
plid,
|
||||||
author_name,
|
author_name,
|
||||||
ucid,
|
ucid,
|
||||||
50,
|
video_count,
|
||||||
Array(SearchPlaylistVideo).new
|
Array(SearchPlaylistVideo).new,
|
||||||
|
thumbnail_id
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -419,7 +443,8 @@ def extract_shelf_items(nodeset, ucid = nil, author_name = nil)
|
|||||||
author_name,
|
author_name,
|
||||||
ucid,
|
ucid,
|
||||||
videos.size,
|
videos.size,
|
||||||
videos
|
videos,
|
||||||
|
videos[0].try &.id
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -162,6 +162,23 @@ def number_with_separator(number)
|
|||||||
number.to_s.reverse.gsub(/(\d{3})(?=\d)/, "\\1,").reverse
|
number.to_s.reverse.gsub(/(\d{3})(?=\d)/, "\\1,").reverse
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def short_text_to_number(short_text)
|
||||||
|
case short_text
|
||||||
|
when .ends_with? "M"
|
||||||
|
number = short_text.rstrip(" mM").to_f
|
||||||
|
number *= 1000000
|
||||||
|
when .ends_with? "K"
|
||||||
|
number = short_text.rstrip(" kK").to_f
|
||||||
|
number *= 1000
|
||||||
|
else
|
||||||
|
number = short_text.rstrip(" ")
|
||||||
|
end
|
||||||
|
|
||||||
|
number = number.to_i
|
||||||
|
|
||||||
|
return number
|
||||||
|
end
|
||||||
|
|
||||||
def number_to_short_text(number)
|
def number_to_short_text(number)
|
||||||
seperated = number_with_separator(number).gsub(",", ".").split("")
|
seperated = number_with_separator(number).gsub(",", ".").split("")
|
||||||
text = seperated.first(2).join
|
text = seperated.first(2).join
|
||||||
|
@ -25,12 +25,13 @@ end
|
|||||||
|
|
||||||
class SearchPlaylist
|
class SearchPlaylist
|
||||||
add_mapping({
|
add_mapping({
|
||||||
title: String,
|
title: String,
|
||||||
id: String,
|
id: String,
|
||||||
author: String,
|
author: String,
|
||||||
ucid: String,
|
ucid: String,
|
||||||
video_count: Int32,
|
video_count: Int32,
|
||||||
videos: Array(SearchPlaylistVideo),
|
videos: Array(SearchPlaylistVideo),
|
||||||
|
thumbnail_id: String?,
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
<h5><%= item.description_html %></h5>
|
<h5><%= item.description_html %></h5>
|
||||||
<% when SearchPlaylist %>
|
<% when SearchPlaylist %>
|
||||||
<% if item.id.starts_with? "RD" %>
|
<% if item.id.starts_with? "RD" %>
|
||||||
<% url = "/mix?list=#{item.id}&continuation=#{item.videos[0]?.try &.id}" %>
|
<% url = "/mix?list=#{item.id}&continuation=#{item.thumbnail_id}" %>
|
||||||
<% else %>
|
<% else %>
|
||||||
<% url = "/playlist?list=#{item.id}" %>
|
<% url = "/playlist?list=#{item.id}" %>
|
||||||
<% end %>
|
<% end %>
|
||||||
@ -24,7 +24,7 @@
|
|||||||
<% if env.get?("user") && env.get("user").as(User).preferences.thin_mode %>
|
<% if env.get?("user") && env.get("user").as(User).preferences.thin_mode %>
|
||||||
<% else %>
|
<% else %>
|
||||||
<div class="thumbnail">
|
<div class="thumbnail">
|
||||||
<img class="thumbnail" src="/vi/<%= item.videos[0]?.try &.id %>/mqdefault.jpg"/>
|
<img class="thumbnail" src="/vi/<%= item.thumbnail_id %>/mqdefault.jpg"/>
|
||||||
<p class="length"><%= number_with_separator(item.video_count) %> videos</p>
|
<p class="length"><%= number_with_separator(item.video_count) %> videos</p>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
@ -79,9 +79,9 @@ var player = videojs("player", options, function() {
|
|||||||
seekStep: 5,
|
seekStep: 5,
|
||||||
enableModifiersForNumbers: false,
|
enableModifiersForNumbers: false,
|
||||||
customKeys: {
|
customKeys: {
|
||||||
|
// Toggle play with K Key
|
||||||
play: {
|
play: {
|
||||||
key: function(e) {
|
key: function(e) {
|
||||||
// Toggle play with K Key
|
|
||||||
return e.which === 75;
|
return e.which === 75;
|
||||||
},
|
},
|
||||||
handler: function(player, options, e) {
|
handler: function(player, options, e) {
|
||||||
@ -92,23 +92,45 @@ var player = videojs("player", options, function() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
// Go backward 5 seconds
|
||||||
backward: {
|
backward: {
|
||||||
key: function(e) {
|
key: function(e) {
|
||||||
// Go backward 5 seconds
|
|
||||||
return e.which === 74;
|
return e.which === 74;
|
||||||
},
|
},
|
||||||
handler: function(player, options, e) {
|
handler: function(player, options, e) {
|
||||||
player.currentTime(player.currentTime() - 5);
|
player.currentTime(player.currentTime() - 5);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
// Go forward 5 seconds
|
||||||
forward: {
|
forward: {
|
||||||
key: function(e) {
|
key: function(e) {
|
||||||
// Go forward 5 seconds
|
|
||||||
return e.which === 76;
|
return e.which === 76;
|
||||||
},
|
},
|
||||||
handler: function(player, options, e) {
|
handler: function(player, options, e) {
|
||||||
player.currentTime(player.currentTime() + 5);
|
player.currentTime(player.currentTime() + 5);
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
// Increase speed
|
||||||
|
increase_speed: {
|
||||||
|
key: function(e) {
|
||||||
|
return e.which === 190;
|
||||||
|
},
|
||||||
|
handler: function(player, _, e) {
|
||||||
|
size = options.playbackRates.length;
|
||||||
|
index = options.playbackRates.indexOf(player.playbackRate());
|
||||||
|
player.playbackRate(options.playbackRates[(index + 1) % size]);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// Decrease speed
|
||||||
|
decrease_speed: {
|
||||||
|
key: function(e) {
|
||||||
|
return e.which === 188;
|
||||||
|
},
|
||||||
|
handler: function(player, _, e) {
|
||||||
|
size = options.playbackRates.length;
|
||||||
|
index = options.playbackRates.indexOf(player.playbackRate());
|
||||||
|
player.playbackRate(options.playbackRates[(size + index - 1) % size]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -9,8 +9,7 @@
|
|||||||
<link rel="stylesheet" href="/css/default.css">
|
<link rel="stylesheet" href="/css/default.css">
|
||||||
<title><%= HTML.escape(video.title) %> - Invidious</title>
|
<title><%= HTML.escape(video.title) %> - Invidious</title>
|
||||||
<style>
|
<style>
|
||||||
video, #my_video, .video-js, .vjs-default-skin
|
#player {
|
||||||
{
|
|
||||||
position: fixed;
|
position: fixed;
|
||||||
right: 0;
|
right: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
|
@ -59,17 +59,17 @@
|
|||||||
<label for="download_widget"><%= translate(locale, "Download as: ") %></label>
|
<label for="download_widget"><%= translate(locale, "Download as: ") %></label>
|
||||||
<select style="width:100%" name="download_widget" id="download_widget">
|
<select style="width:100%" name="download_widget" id="download_widget">
|
||||||
<% video_streams.each do |option| %>
|
<% video_streams.each do |option| %>
|
||||||
<option value='{"id":"<%= video.id %>","itag":"<%= option["itag"] %>","title":"<%= URI.escape(video.title) %>-<%= video.id %>.mp4"}'>
|
<option value='{"id":"<%= video.id %>","itag":"<%= option["itag"] %>","title":"<%= URI.escape(video.title) %>-<%= video.id %>.<%= option["type"].split("/")[1].split(";")[0] %>"}'>
|
||||||
<%= option["quality_label"] %> - <%= option["type"].split(";")[0] %> @ <%= option["fps"] %>fps - video only
|
<%= option["quality_label"] %> - <%= option["type"].split(";")[0] %> @ <%= option["fps"] %>fps - video only
|
||||||
</option>
|
</option>
|
||||||
<% end %>
|
<% end %>
|
||||||
<% audio_streams.each do |option| %>
|
<% audio_streams.each do |option| %>
|
||||||
<option value='{"id":"<%= video.id %>","itag":"<%= option["itag"] %>","title":"<%= URI.escape(video.title) %>-<%= video.id %>.mp4"}'>
|
<option value='{"id":"<%= video.id %>","itag":"<%= option["itag"] %>","title":"<%= URI.escape(video.title) %>-<%= video.id %>.<%= option["type"].split("/")[1].split(";")[0] %>"}'>
|
||||||
<%= option["type"].split(";")[0] %> @ <%= option["bitrate"] %>k - audio only
|
<%= option["type"].split(";")[0] %> @ <%= option["bitrate"] %>k - audio only
|
||||||
</option>
|
</option>
|
||||||
<% end %>
|
<% end %>
|
||||||
<% fmt_stream.each do |option| %>
|
<% fmt_stream.each do |option| %>
|
||||||
<option value='{"id":"<%= video.id %>","itag":"<%= option["itag"] %>","title":"<%= URI.escape(video.title) %>-<%= video.id %>.mp4"}'>
|
<option value='{"id":"<%= video.id %>","itag":"<%= option["itag"] %>","title":"<%= URI.escape(video.title) %>-<%= video.id %>.<%= option["type"].split("/")[1].split(";")[0] %>"}'>
|
||||||
<%= itag_to_metadata?(option["itag"]).try &.["height"]? || "~240" %>p - <%= option["type"].split(";")[0] %>
|
<%= itag_to_metadata?(option["itag"]).try &.["height"]? || "~240" %>p - <%= option["type"].split(";")[0] %>
|
||||||
</option>
|
</option>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
Loading…
Reference in New Issue
Block a user