mirror of
https://github.com/iv-org/invidious.git
synced 2025-07-09 13:45:46 -05:00
Merge c9c69e850d11d535a5647f15f4057638c4d71689 into 2c857b5ab6af36ec625fad688db6673f5d150d20
This commit is contained in:
commit
fdba3d7cf5
@ -4,7 +4,7 @@ module Invidious::HttpServer
|
||||
module Utils
|
||||
extend self
|
||||
|
||||
def proxy_video_url(raw_url : String, *, region : String? = nil, absolute : Bool = false)
|
||||
def proxy_video_url(raw_url : String, *, region : String? = nil, absolute : Bool = false, host : String? = "")
|
||||
url = URI.parse(raw_url)
|
||||
|
||||
# Add some URL parameters
|
||||
@ -14,7 +14,7 @@ module Invidious::HttpServer
|
||||
url.query_params = params
|
||||
|
||||
if absolute
|
||||
return "#{HOST_URL}#{url.request_target}"
|
||||
return "#{host}#{url.request_target}"
|
||||
else
|
||||
return url.request_target
|
||||
end
|
||||
|
@ -1,6 +1,8 @@
|
||||
module Invidious::Routes::API::Manifest
|
||||
# /api/manifest/dash/id/:id
|
||||
def self.get_dash_video_id(env)
|
||||
host = env.request.headers["Host"]
|
||||
|
||||
env.response.headers.add("Access-Control-Allow-Origin", "*")
|
||||
env.response.content_type = "application/dash+xml"
|
||||
|
||||
@ -36,7 +38,7 @@ module Invidious::Routes::API::Manifest
|
||||
# Other API clients can get the original URLs by omiting `local=true`.
|
||||
manifest = response.body.gsub(/<BaseURL>[^<]+<\/BaseURL>/) do |baseurl|
|
||||
url = baseurl.lchop("<BaseURL>").rchop("</BaseURL>")
|
||||
url = HttpServer::Utils.proxy_video_url(url, absolute: true) if local
|
||||
url = HttpServer::Utils.proxy_video_url(url, absolute: true, host: host) if local
|
||||
"<BaseURL>#{url}</BaseURL>"
|
||||
end
|
||||
|
||||
@ -46,7 +48,7 @@ module Invidious::Routes::API::Manifest
|
||||
# Ditto, only proxify URLs if `local=true` is used
|
||||
if local
|
||||
video.adaptive_fmts.each do |fmt|
|
||||
fmt["url"] = JSON::Any.new(HttpServer::Utils.proxy_video_url(fmt["url"].as_s, absolute: true))
|
||||
fmt["url"] = JSON::Any.new(HttpServer::Utils.proxy_video_url(fmt["url"].as_s, absolute: true, host: host))
|
||||
end
|
||||
end
|
||||
|
||||
@ -167,6 +169,8 @@ module Invidious::Routes::API::Manifest
|
||||
|
||||
# /api/manifest/hls_playlist/*
|
||||
def self.get_hls_playlist(env)
|
||||
host = env.request.headers["Host"]
|
||||
|
||||
response = YT_POOL.client &.get(env.request.path)
|
||||
|
||||
if response.status_code != 200
|
||||
@ -214,7 +218,7 @@ module Invidious::Routes::API::Manifest
|
||||
|
||||
raw_params["host"] = uri.host.not_nil!
|
||||
|
||||
"#{HOST_URL}/videoplayback?#{raw_params}"
|
||||
"#{host}/videoplayback?#{raw_params}"
|
||||
end
|
||||
end
|
||||
|
||||
@ -223,6 +227,8 @@ module Invidious::Routes::API::Manifest
|
||||
|
||||
# /api/manifest/hls_variant/*
|
||||
def self.get_hls_variant(env)
|
||||
host = env.request.headers["Host"]
|
||||
|
||||
response = YT_POOL.client &.get(env.request.path)
|
||||
|
||||
if response.status_code != 200
|
||||
@ -237,7 +243,7 @@ module Invidious::Routes::API::Manifest
|
||||
manifest = response.body
|
||||
|
||||
if local
|
||||
manifest = manifest.gsub("https://www.youtube.com", HOST_URL)
|
||||
manifest = manifest.gsub("https://www.youtube.com", host)
|
||||
manifest = manifest.gsub("index.m3u8", "index.m3u8?local=true")
|
||||
end
|
||||
|
||||
|
@ -208,6 +208,8 @@ module Invidious::Routes::API::V1::Authenticated
|
||||
end
|
||||
|
||||
def self.create_playlist(env)
|
||||
host = env.request.headers["Host"]
|
||||
|
||||
env.response.content_type = "application/json"
|
||||
user = env.get("user").as(User)
|
||||
|
||||
@ -226,7 +228,7 @@ module Invidious::Routes::API::V1::Authenticated
|
||||
end
|
||||
|
||||
playlist = create_playlist(title, privacy, user)
|
||||
env.response.headers["Location"] = "#{HOST_URL}/api/v1/auth/playlists/#{playlist.id}"
|
||||
env.response.headers["Location"] = "#{host}/api/v1/auth/playlists/#{playlist.id}"
|
||||
env.response.status_code = 201
|
||||
{
|
||||
"title" => title,
|
||||
@ -290,6 +292,8 @@ module Invidious::Routes::API::V1::Authenticated
|
||||
end
|
||||
|
||||
def self.insert_video_into_playlist(env)
|
||||
host = env.request.headers["Host"]
|
||||
|
||||
env.response.content_type = "application/json"
|
||||
user = env.get("user").as(User)
|
||||
|
||||
@ -336,7 +340,7 @@ module Invidious::Routes::API::V1::Authenticated
|
||||
Invidious::Database::PlaylistVideos.insert(playlist_video)
|
||||
Invidious::Database::Playlists.update_video_added(plid, playlist_video.index)
|
||||
|
||||
env.response.headers["Location"] = "#{HOST_URL}/api/v1/auth/playlists/#{plid}/videos/#{playlist_video.index.to_u64.to_s(16).upcase}"
|
||||
env.response.headers["Location"] = "#{host}/api/v1/auth/playlists/#{plid}/videos/#{playlist_video.index.to_u64.to_s(16).upcase}"
|
||||
env.response.status_code = 201
|
||||
|
||||
JSON.build do |json|
|
||||
|
@ -34,6 +34,7 @@ module Invidious::Routes::Embed
|
||||
|
||||
def self.show(env)
|
||||
locale = env.get("preferences").as(Preferences).locale
|
||||
host = env.request.headers["Host"]
|
||||
id = env.params.url["id"]
|
||||
|
||||
plid = env.params.query["list"]?.try &.gsub(/[^a-zA-Z0-9_-]/, "")
|
||||
@ -161,11 +162,11 @@ module Invidious::Routes::Embed
|
||||
adaptive_fmts = video.adaptive_fmts
|
||||
|
||||
if params.local
|
||||
fmt_stream.each { |fmt| fmt["url"] = JSON::Any.new(HttpServer::Utils.proxy_video_url(fmt["url"].as_s)) }
|
||||
fmt_stream.each { |fmt| fmt["url"] = JSON::Any.new(HttpServer::Utils.proxy_video_url(fmt["url"].as_s, host: host)) }
|
||||
end
|
||||
|
||||
# Always proxy DASH streams, otherwise youtube CORS headers will prevent playback
|
||||
adaptive_fmts.each { |fmt| fmt["url"] = JSON::Any.new(HttpServer::Utils.proxy_video_url(fmt["url"].as_s)) }
|
||||
adaptive_fmts.each { |fmt| fmt["url"] = JSON::Any.new(HttpServer::Utils.proxy_video_url(fmt["url"].as_s, host: host)) }
|
||||
|
||||
video_streams = video.video_streams
|
||||
audio_streams = video.audio_streams
|
||||
|
@ -1,7 +1,7 @@
|
||||
module Invidious::Routes::ErrorRoutes
|
||||
def self.error_404(env)
|
||||
# Workaround for #3117
|
||||
if HOST_URL.empty? && env.request.path.starts_with?("/v1/storyboards/sb")
|
||||
if env.request.headers["Host"].empty? && env.request.path.starts_with?("/v1/storyboards/sb")
|
||||
return env.redirect "#{env.request.path[15..]}?#{env.params.query}"
|
||||
end
|
||||
|
||||
|
@ -143,6 +143,8 @@ module Invidious::Routes::Feeds
|
||||
# RSS feeds
|
||||
|
||||
def self.rss_channel(env)
|
||||
host = env.request.headers["Host"]
|
||||
|
||||
env.response.headers["Content-Type"] = "application/atom+xml"
|
||||
env.response.content_type = "application/atom+xml"
|
||||
|
||||
@ -199,21 +201,21 @@ module Invidious::Routes::Feeds
|
||||
xml.element("feed", "xmlns:yt": "http://www.youtube.com/xml/schemas/2015",
|
||||
"xmlns:media": "http://search.yahoo.com/mrss/", xmlns: "http://www.w3.org/2005/Atom",
|
||||
"xml:lang": "en-US") do
|
||||
xml.element("link", rel: "self", href: "#{HOST_URL}#{env.request.resource}")
|
||||
xml.element("link", rel: "self", href: "#{host}#{env.request.resource}")
|
||||
xml.element("id") { xml.text "yt:channel:#{ucid}" }
|
||||
xml.element("yt:channelId") { xml.text ucid }
|
||||
xml.element("title") { author }
|
||||
xml.element("link", rel: "alternate", href: "#{HOST_URL}/channel/#{ucid}")
|
||||
xml.element("link", rel: "alternate", href: "#{host}/channel/#{ucid}")
|
||||
|
||||
xml.element("author") do
|
||||
xml.element("name") { xml.text author }
|
||||
xml.element("uri") { xml.text "#{HOST_URL}/channel/#{ucid}" }
|
||||
xml.element("uri") { xml.text "#{host}/channel/#{ucid}" }
|
||||
end
|
||||
|
||||
xml.element("image") do
|
||||
xml.element("url") { xml.text "" }
|
||||
xml.element("title") { xml.text author }
|
||||
xml.element("link", rel: "self", href: "#{HOST_URL}#{env.request.resource}")
|
||||
xml.element("link", rel: "self", href: "#{host}#{env.request.resource}")
|
||||
end
|
||||
|
||||
videos.each do |video|
|
||||
@ -225,6 +227,7 @@ module Invidious::Routes::Feeds
|
||||
|
||||
def self.rss_private(env)
|
||||
locale = env.get("preferences").as(Preferences).locale
|
||||
host = env.request.headers["Host"]
|
||||
|
||||
env.response.headers["Content-Type"] = "application/atom+xml"
|
||||
env.response.content_type = "application/atom+xml"
|
||||
@ -255,9 +258,9 @@ module Invidious::Routes::Feeds
|
||||
xml.element("feed", "xmlns:yt": "http://www.youtube.com/xml/schemas/2015",
|
||||
"xmlns:media": "http://search.yahoo.com/mrss/", xmlns: "http://www.w3.org/2005/Atom",
|
||||
"xml:lang": "en-US") do
|
||||
xml.element("link", "type": "text/html", rel: "alternate", href: "#{HOST_URL}/feed/subscriptions")
|
||||
xml.element("link", "type": "text/html", rel: "alternate", href: "#{host}/feed/subscriptions")
|
||||
xml.element("link", "type": "application/atom+xml", rel: "self",
|
||||
href: "#{HOST_URL}#{env.request.resource}")
|
||||
href: "#{host}#{env.request.resource}")
|
||||
xml.element("title") { xml.text translate(locale, "Invidious Private Feed for `x`", user.email) }
|
||||
|
||||
(notifications + videos).each do |video|
|
||||
@ -269,6 +272,7 @@ module Invidious::Routes::Feeds
|
||||
|
||||
def self.rss_playlist(env)
|
||||
locale = env.get("preferences").as(Preferences).locale
|
||||
host = env.request.headers["Host"]
|
||||
|
||||
env.response.headers["Content-Type"] = "application/atom+xml"
|
||||
env.response.content_type = "application/atom+xml"
|
||||
@ -286,11 +290,11 @@ module Invidious::Routes::Feeds
|
||||
xml.element("feed", "xmlns:yt": "http://www.youtube.com/xml/schemas/2015",
|
||||
"xmlns:media": "http://search.yahoo.com/mrss/", xmlns: "http://www.w3.org/2005/Atom",
|
||||
"xml:lang": "en-US") do
|
||||
xml.element("link", rel: "self", href: "#{HOST_URL}#{env.request.resource}")
|
||||
xml.element("link", rel: "self", href: "#{host}#{env.request.resource}")
|
||||
xml.element("id") { xml.text "iv:playlist:#{plid}" }
|
||||
xml.element("iv:playlistId") { xml.text plid }
|
||||
xml.element("title") { xml.text playlist.title }
|
||||
xml.element("link", rel: "alternate", href: "#{HOST_URL}/playlist?list=#{plid}")
|
||||
xml.element("link", rel: "alternate", href: "#{host}/playlist?list=#{plid}")
|
||||
|
||||
xml.element("author") do
|
||||
xml.element("name") { xml.text playlist.author }
|
||||
@ -320,7 +324,7 @@ module Invidious::Routes::Feeds
|
||||
when "url", "href"
|
||||
request_target = URI.parse(node[attribute.name]).request_target
|
||||
query_string_opt = request_target.starts_with?("/watch?v=") ? "&#{params}" : ""
|
||||
node[attribute.name] = "#{HOST_URL}#{request_target}#{query_string_opt}"
|
||||
node[attribute.name] = "#{host}#{request_target}#{query_string_opt}"
|
||||
else nil # Skip
|
||||
end
|
||||
end
|
||||
@ -329,7 +333,7 @@ module Invidious::Routes::Feeds
|
||||
document = document.to_xml(options: XML::SaveOptions::NO_DECL)
|
||||
|
||||
document.scan(/<uri>(?<url>[^<]+)<\/uri>/).each do |match|
|
||||
content = "#{HOST_URL}#{URI.parse(match["url"]).request_target}"
|
||||
content = "#{host}#{URI.parse(match["url"]).request_target}"
|
||||
document = document.gsub(match[0], "<uri>#{content}</uri>")
|
||||
end
|
||||
document
|
||||
|
@ -26,6 +26,7 @@ module Invidious::Routes::Login
|
||||
|
||||
def self.login(env)
|
||||
locale = env.get("preferences").as(Preferences).locale
|
||||
host = env.request.headers["Host"]
|
||||
|
||||
referer = get_referer(env, "/feed/subscriptions")
|
||||
|
||||
@ -57,7 +58,7 @@ module Invidious::Routes::Login
|
||||
sid = Base64.urlsafe_encode(Random::Secure.random_bytes(32))
|
||||
Invidious::Database::SessionIDs.insert(sid, email)
|
||||
|
||||
env.response.cookies["SID"] = Invidious::User::Cookies.sid(CONFIG.domain, sid)
|
||||
env.response.cookies["SID"] = Invidious::User::Cookies.sid(host, sid)
|
||||
else
|
||||
return error_template(401, "Wrong username or password")
|
||||
end
|
||||
@ -121,7 +122,7 @@ module Invidious::Routes::Login
|
||||
view_name = "subscriptions_#{sha256(user.email)}"
|
||||
PG_DB.exec("CREATE MATERIALIZED VIEW #{view_name} AS #{MATERIALIZED_VIEW_SQL.call(user.email)}")
|
||||
|
||||
env.response.cookies["SID"] = Invidious::User::Cookies.sid(CONFIG.domain, sid)
|
||||
env.response.cookies["SID"] = Invidious::User::Cookies.sid(host, sid)
|
||||
|
||||
if env.request.cookies["PREFS"]?
|
||||
user.preferences = env.get("preferences").as(Preferences)
|
||||
|
@ -14,6 +14,7 @@ module Invidious::Routes::PreferencesRoute
|
||||
def self.update(env)
|
||||
locale = env.get("preferences").as(Preferences).locale
|
||||
referer = get_referer(env)
|
||||
host = env.request.headers["Host"]
|
||||
|
||||
video_loop = env.params.body["video_loop"]?.try &.as(String)
|
||||
video_loop ||= "off"
|
||||
@ -223,8 +224,8 @@ module Invidious::Routes::PreferencesRoute
|
||||
|
||||
File.write("config/config.yml", CONFIG.to_yaml)
|
||||
end
|
||||
else
|
||||
env.response.cookies["PREFS"] = Invidious::User::Cookies.prefs(CONFIG.domain, preferences)
|
||||
|
||||
env.response.cookies["PREFS"] = Invidious::User::Cookies.prefs(host, preferences)
|
||||
end
|
||||
|
||||
env.redirect referer
|
||||
@ -233,6 +234,7 @@ module Invidious::Routes::PreferencesRoute
|
||||
def self.toggle_theme(env)
|
||||
locale = env.get("preferences").as(Preferences).locale
|
||||
referer = get_referer(env, unroll: false)
|
||||
host = env.request.headers["Host"]
|
||||
|
||||
redirect = env.params.query["redirect"]?
|
||||
redirect ||= "true"
|
||||
@ -259,7 +261,7 @@ module Invidious::Routes::PreferencesRoute
|
||||
preferences.dark_mode = "dark"
|
||||
end
|
||||
|
||||
env.response.cookies["PREFS"] = Invidious::User::Cookies.prefs(CONFIG.domain, preferences)
|
||||
env.response.cookies["PREFS"] = Invidious::User::Cookies.prefs(host, preferences)
|
||||
end
|
||||
|
||||
if redirect
|
||||
|
@ -3,6 +3,8 @@
|
||||
module Invidious::Routes::Search
|
||||
def self.opensearch(env)
|
||||
locale = env.get("preferences").as(Preferences).locale
|
||||
host = env.request.headers["Host"]
|
||||
|
||||
env.response.content_type = "application/opensearchdescription+xml"
|
||||
|
||||
XML.build(indent: " ", encoding: "UTF-8") do |xml|
|
||||
@ -11,8 +13,8 @@ module Invidious::Routes::Search
|
||||
xml.element("LongName") { xml.text "Invidious Search" }
|
||||
xml.element("Description") { xml.text "Search for videos, channels, and playlists on Invidious" }
|
||||
xml.element("InputEncoding") { xml.text "UTF-8" }
|
||||
xml.element("Image", width: 48, height: 48, type: "image/x-icon") { xml.text "#{HOST_URL}/favicon.ico" }
|
||||
xml.element("Url", type: "text/html", method: "get", template: "#{HOST_URL}/search?q={searchTerms}")
|
||||
xml.element("Image", width: 48, height: 48, type: "image/x-icon") { xml.text "#{host}/favicon.ico" }
|
||||
xml.element("Url", type: "text/html", method: "get", template: "#{host}/search?q={searchTerms}")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -2,6 +2,7 @@ module Invidious::Routes::VideoPlayback
|
||||
# /videoplayback
|
||||
def self.get_video_playback(env)
|
||||
locale = env.get("preferences").as(Preferences).locale
|
||||
host_ = env.request.headers["Host"]
|
||||
query_params = env.params.query
|
||||
|
||||
fvip = query_params["fvip"]? || "3"
|
||||
@ -107,7 +108,7 @@ module Invidious::Routes::VideoPlayback
|
||||
env.response.headers["Access-Control-Allow-Origin"] = "*"
|
||||
|
||||
if location = resp.headers["Location"]?
|
||||
url = Invidious::HttpServer::Utils.proxy_video_url(location, region: region)
|
||||
url = Invidious::HttpServer::Utils.proxy_video_url(location, region: region, host: host_)
|
||||
return env.redirect url
|
||||
end
|
||||
|
||||
@ -165,7 +166,7 @@ module Invidious::Routes::VideoPlayback
|
||||
env.response.headers["Access-Control-Allow-Origin"] = "*"
|
||||
|
||||
if location = resp.headers["Location"]?
|
||||
url = Invidious::HttpServer::Utils.proxy_video_url(location, region: region)
|
||||
url = Invidious::HttpServer::Utils.proxy_video_url(location, region: region, host: host_)
|
||||
|
||||
if title = query_params["title"]?
|
||||
url = "#{url}&title=#{URI.encode_www_form(title)}"
|
||||
|
@ -4,6 +4,7 @@ module Invidious::Routes::Watch
|
||||
def self.handle(env)
|
||||
locale = env.get("preferences").as(Preferences).locale
|
||||
region = env.params.query["region"]?
|
||||
host = env.request.headers["Host"]
|
||||
|
||||
if env.params.query.to_s.includes?("%20") || env.params.query.to_s.includes?("+")
|
||||
url = "/watch?" + env.params.query.to_s.gsub("%20", "").delete("+")
|
||||
@ -121,11 +122,11 @@ module Invidious::Routes::Watch
|
||||
adaptive_fmts = video.adaptive_fmts
|
||||
|
||||
if params.local
|
||||
fmt_stream.each { |fmt| fmt["url"] = JSON::Any.new(HttpServer::Utils.proxy_video_url(fmt["url"].as_s)) }
|
||||
fmt_stream.each { |fmt| fmt["url"] = JSON::Any.new(HttpServer::Utils.proxy_video_url(fmt["url"].as_s, host: host)) }
|
||||
end
|
||||
|
||||
# Always proxy DASH streams, otherwise youtube CORS headers will prevent playback
|
||||
adaptive_fmts.each { |fmt| fmt["url"] = JSON::Any.new(HttpServer::Utils.proxy_video_url(fmt["url"].as_s)) }
|
||||
adaptive_fmts.each { |fmt| fmt["url"] = JSON::Any.new(HttpServer::Utils.proxy_video_url(fmt["url"].as_s, host: host)) }
|
||||
|
||||
video_streams = video.video_streams
|
||||
audio_streams = video.audio_streams
|
||||
|
@ -6,17 +6,23 @@ struct Invidious::User
|
||||
|
||||
# Note: we use ternary operator because the two variables
|
||||
# used in here are not booleans.
|
||||
SECURE = (Kemal.config.ssl || CONFIG.https_only) ? true : false
|
||||
@@secure = (Kemal.config.ssl || CONFIG.https_only) ? true : false
|
||||
|
||||
# Session ID (SID) cookie
|
||||
# Parameter "domain" comes from the global config
|
||||
def sid(domain : String?, sid) : HTTP::Cookie
|
||||
# Not secure if it's being accessed from I2P
|
||||
# Browsers expect the domain to include https. On I2P there is no HTTPS
|
||||
if domain.not_nil!.split(".").last == "i2p"
|
||||
@@secure = false
|
||||
end
|
||||
|
||||
return HTTP::Cookie.new(
|
||||
name: "SID",
|
||||
domain: domain,
|
||||
value: sid,
|
||||
expires: Time.utc + 2.years,
|
||||
secure: SECURE,
|
||||
secure: @@secure,
|
||||
http_only: true,
|
||||
samesite: HTTP::Cookie::SameSite::Lax
|
||||
)
|
||||
@ -25,12 +31,18 @@ struct Invidious::User
|
||||
# Preferences (PREFS) cookie
|
||||
# Parameter "domain" comes from the global config
|
||||
def prefs(domain : String?, preferences : Preferences) : HTTP::Cookie
|
||||
# Not secure if it's being accessed from I2P
|
||||
# Browsers expect the domain to include https. On I2P there is no HTTPS
|
||||
if domain.not_nil!.split(".").last == "i2p"
|
||||
@@secure = false
|
||||
end
|
||||
|
||||
return HTTP::Cookie.new(
|
||||
name: "PREFS",
|
||||
domain: domain,
|
||||
value: URI.encode_www_form(preferences.to_json),
|
||||
expires: Time.utc + 2.years,
|
||||
secure: SECURE,
|
||||
secure: @@secure,
|
||||
http_only: false,
|
||||
samesite: HTTP::Cookie::SameSite::Lax
|
||||
)
|
||||
|
@ -25,21 +25,22 @@
|
||||
first_page: continuation.nil?,
|
||||
params: env.params.query,
|
||||
)
|
||||
host = env.request.headers["Host"]
|
||||
%>
|
||||
|
||||
<% content_for "header" do %>
|
||||
<%- if selected_tab.videos? -%>
|
||||
<meta name="description" content="<%= channel.description %>">
|
||||
<meta property="og:site_name" content="Invidious">
|
||||
<meta property="og:url" content="<%= HOST_URL %>/channel/<%= ucid %>">
|
||||
<meta property="og:url" content="<%= host %>/channel/<%= ucid %>">
|
||||
<meta property="og:title" content="<%= author %>">
|
||||
<meta property="og:image" content="<%= HOST_URL %>/ggpht<%= channel_profile_pic %>">
|
||||
<meta property="og:image" content="<%= host %>/ggpht<%= channel_profile_pic %>">
|
||||
<meta property="og:description" content="<%= channel.description %>">
|
||||
<meta name="twitter:card" content="summary">
|
||||
<meta name="twitter:url" content="<%= HOST_URL %>/channel/<%= ucid %>">
|
||||
<meta name="twitter:url" content="<%= host %>/channel/<%= ucid %>">
|
||||
<meta name="twitter:title" content="<%= author %>">
|
||||
<meta name="twitter:description" content="<%= channel.description %>">
|
||||
<meta name="twitter:image" content="<%= HOST_URL %>/ggpht<%= channel_profile_pic %>">
|
||||
<meta name="twitter:image" content="<%= host %>/ggpht<%= channel_profile_pic %>">
|
||||
<link rel="alternate" type="application/rss+xml" title="RSS" href="/feed/channel/<%= ucid %>" />
|
||||
<%- end -%>
|
||||
|
||||
|
@ -1,29 +1,29 @@
|
||||
<% ucid = video.ucid %>
|
||||
<% title = HTML.escape(video.title) %>
|
||||
<% author = HTML.escape(video.author) %>
|
||||
|
||||
<% host = env.request.headers["Host"] %>
|
||||
|
||||
<% content_for "header" do %>
|
||||
<meta name="thumbnail" content="<%= thumbnail %>">
|
||||
<meta name="description" content="<%= HTML.escape(video.short_description) %>">
|
||||
<meta name="keywords" content="<%= video.keywords.join(",") %>">
|
||||
<meta property="og:site_name" content="<%= author %> | Invidious">
|
||||
<meta property="og:url" content="<%= HOST_URL %>/watch?v=<%= video.id %>">
|
||||
<meta property="og:url" content="<%= host %>/watch?v=<%= video.id %>">
|
||||
<meta property="og:title" content="<%= title %>">
|
||||
<meta property="og:image" content="<%= HOST_URL %>/vi/<%= video.id %>/maxres.jpg">
|
||||
<meta property="og:image" content="<%= host %>/vi/<%= video.id %>/maxres.jpg">
|
||||
<meta property="og:description" content="<%= HTML.escape(video.short_description) %>">
|
||||
<meta property="og:type" content="video.other">
|
||||
<meta property="og:video:url" content="<%= HOST_URL %>/embed/<%= video.id %>">
|
||||
<meta property="og:video:secure_url" content="<%= HOST_URL %>/embed/<%= video.id %>">
|
||||
<meta property="og:video:url" content="<%= host %>/embed/<%= video.id %>">
|
||||
<meta property="og:video:secure_url" content="<%= host %>/embed/<%= video.id %>">
|
||||
<meta property="og:video:type" content="text/html">
|
||||
<meta property="og:video:width" content="1280">
|
||||
<meta property="og:video:height" content="720">
|
||||
<meta name="twitter:card" content="player">
|
||||
<meta name="twitter:url" content="<%= HOST_URL %>/watch?v=<%= video.id %>">
|
||||
<meta name="twitter:url" content="<%= host %>/watch?v=<%= video.id %>">
|
||||
<meta name="twitter:title" content="<%= title %>">
|
||||
<meta name="twitter:description" content="<%= HTML.escape(video.short_description) %>">
|
||||
<meta name="twitter:image" content="<%= HOST_URL %>/vi/<%= video.id %>/maxres.jpg">
|
||||
<meta name="twitter:player" content="<%= HOST_URL %>/embed/<%= video.id %>">
|
||||
<meta name="twitter:image" content="<%= host %>/vi/<%= video.id %>/maxres.jpg">
|
||||
<meta name="twitter:player" content="<%= host %>/embed/<%= video.id %>">
|
||||
<meta name="twitter:player:width" content="1280">
|
||||
<meta name="twitter:player:height" content="720">
|
||||
<link rel="alternate" href="https://www.youtube.com/watch?v=<%= video.id %>">
|
||||
|
Loading…
x
Reference in New Issue
Block a user