summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--assets/css/default.css25
-rw-r--r--locales/da.json212
-rw-r--r--src/invidious.cr13
-rw-r--r--src/invidious/channels.cr110
-rw-r--r--src/invidious/helpers/helpers.cr2
-rw-r--r--src/invidious/jobs/statistics_refresh_job.cr2
-rw-r--r--src/invidious/playlists.cr3
-rw-r--r--src/invidious/routes/watch.cr9
-rw-r--r--src/invidious/users.cr2
-rw-r--r--src/invidious/videos.cr18
-rw-r--r--src/invidious/views/template.ecr6
11 files changed, 231 insertions, 171 deletions
diff --git a/assets/css/default.css b/assets/css/default.css
index a5148f5b..a725b456 100644
--- a/assets/css/default.css
+++ b/assets/css/default.css
@@ -5,6 +5,12 @@ body {
Arial, sans-serif;
}
+#contents {
+ display: flex;
+ flex-direction: column;
+ min-height: 100vh;
+}
+
.deleted {
background-color: rgb(255, 0, 0, 0.5);
}
@@ -280,14 +286,16 @@ input[type="search"]::-webkit-search-cancel-button {
* Footer
*/
-.footer {
- color: #666666;
- margin: 2em 0;
+footer {
+ color: #919191;
+ margin-top: auto;
+ padding: 1.5em 0;
text-align: center;
+ max-height: 30vh;
}
-body .footer a {
- color: inherit;
+footer a {
+ color: #919191 !important;
text-decoration: underline;
}
@@ -654,3 +662,10 @@ body.dark-theme {
content: "[ - ]";
font-size: 1.5em;
}
+
+/*With commit d9528f5 all contents of the page is now within a flexbox. However,
+the hr element is rendered improperly within one.
+See https://stackoverflow.com/a/34372979 for more info */
+hr {
+ margin: auto 0 auto 0;
+}
diff --git a/locales/da.json b/locales/da.json
index 4d265062..b52905c3 100644
--- a/locales/da.json
+++ b/locales/da.json
@@ -13,7 +13,7 @@
},
"LIVE": "DIREKTE",
"Shared `x` ago": "Delt for `x` siden",
- "Unsubscribe": "",
+ "Unsubscribe": "Opsig abonnement",
"Subscribe": "Abonner",
"View channel on YouTube": "Vis kanal på YouTube",
"View playlist on YouTube": "Vis afspilningsliste på YouTube",
@@ -28,13 +28,13 @@
"New passwords must match": "Nye kodeord skal matche",
"Cannot change password for Google accounts": "Kan ikke skifte kodeord til Google-konti",
"Authorize token?": "Godkend token?",
- "Authorize token for `x`?": "Godkende token til `x`?",
+ "Authorize token for `x`?": "Godkend token til `x`?",
"Yes": "Ja",
"No": "Nej",
"Import and Export Data": "Importer og Eksporter Data",
"Import": "Importer",
"Import Invidious data": "Importer Invidious data",
- "Import YouTube subscriptions": "Importer Youtube abonnementer",
+ "Import YouTube subscriptions": "Importer YouTube abonnementer",
"Import FreeTube subscriptions (.db)": "Importer FreeTube abonnementer (.db)",
"Import NewPipe subscriptions (.json)": "Importer NewPipe abonnementer (.json)",
"Import NewPipe data (.zip)": "Importer NewPipe data (.zip)",
@@ -58,9 +58,9 @@
"Sign In": "Log ind",
"Register": "Registrer",
"E-mail": "E-mail",
- "Google verification code": "Google verifications kode",
+ "Google verification code": "Google-verifikationskode",
"Preferences": "Præferencer",
- "Player preferences": "",
+ "Player preferences": "Afspillerindstillinger",
"Always loop: ": "Altid gentag: ",
"Autoplay: ": "Auto afspil: ",
"Play next by default: ": "Afspil næste som standard: ",
@@ -74,118 +74,118 @@
"youtube": "youtube",
"reddit": "reddit",
"Default captions: ": "Standard undertekster: ",
- "Fallback captions: ": "",
- "Show related videos: ": "",
- "Show annotations by default: ": "",
- "Visual preferences": "",
- "Player style: ": "",
- "Dark mode: ": "",
- "Theme: ": "",
- "dark": "",
- "light": "",
- "Thin mode: ": "",
- "Subscription preferences": "",
- "Show annotations by default for subscribed channels: ": "",
- "Redirect homepage to feed: ": "",
- "Number of videos shown in feed: ": "",
- "Sort videos by: ": "",
- "published": "",
- "published - reverse": "",
- "alphabetically": "",
- "alphabetically - reverse": "",
- "channel name": "",
- "channel name - reverse": "",
- "Only show latest video from channel: ": "",
- "Only show latest unwatched video from channel: ": "",
- "Only show unwatched: ": "",
- "Only show notifications (if there are any): ": "",
- "Enable web notifications": "",
- "`x` uploaded a video": "",
- "`x` is live": "",
- "Data preferences": "",
- "Clear watch history": "",
- "Import/export data": "",
- "Change password": "",
- "Manage subscriptions": "",
- "Manage tokens": "",
- "Watch history": "",
- "Delete account": "",
- "Administrator preferences": "",
- "Default homepage: ": "",
- "Feed menu: ": "",
- "Top enabled: ": "",
- "CAPTCHA enabled: ": "",
- "Login enabled: ": "",
- "Registration enabled: ": "",
- "Report statistics: ": "",
- "Save preferences": "",
- "Subscription manager": "",
- "Token manager": "",
- "Token": "",
+ "Fallback captions: ": "Alternative undertekster: ",
+ "Show related videos: ": "Vis relaterede videoer: ",
+ "Show annotations by default: ": "Vis annotationer som standard: ",
+ "Visual preferences": "Visuelle præferencer",
+ "Player style: ": "Afspiller stil: ",
+ "Dark mode: ": "Mørk tilstand: ",
+ "Theme: ": "Tema: ",
+ "dark": "mørk",
+ "light": "lys",
+ "Thin mode: ": "Tynd tilstand: ",
+ "Subscription preferences": "Abonnements præferencer",
+ "Show annotations by default for subscribed channels: ": "Vis annotationer som standard for abonnerede kanaler: ",
+ "Redirect homepage to feed: ": "Omdiriger startside til feed: ",
+ "Number of videos shown in feed: ": "Antal videoer vist i feed: ",
+ "Sort videos by: ": "Sorter videoer efter: ",
+ "published": "offentliggjort",
+ "published - reverse": "offentliggjort - omvendt",
+ "alphabetically": "alfabetisk",
+ "alphabetically - reverse": "alfabetisk - omvendt",
+ "channel name": "kanalnavn",
+ "channel name - reverse": "kanalnavn - omvendt",
+ "Only show latest video from channel: ": "Vis kun seneste video fra kanal: ",
+ "Only show latest unwatched video from channel: ": "Vis kun seneste usete video fra kanal: ",
+ "Only show unwatched: ": "Vis kun usete: ",
+ "Only show notifications (if there are any): ": "Vis kun notifikationer (hvis der er nogle): ",
+ "Enable web notifications": "Aktiver webnotifikationer",
+ "`x` uploaded a video": "`x` uploadede en video",
+ "`x` is live": "`x` er live",
+ "Data preferences": "Data præferencer",
+ "Clear watch history": "Ryd afspilningshistorik",
+ "Import/export data": "Importer/exporter data",
+ "Change password": "Skift adgangskode",
+ "Manage subscriptions": "Administrer abonnementer",
+ "Manage tokens": "Administrer tokens",
+ "Watch history": "Afspilningshistorik",
+ "Delete account": "Slet konto",
+ "Administrator preferences": "Administrator præferencer",
+ "Default homepage: ": "Standard startside: ",
+ "Feed menu: ": "Feed menu: ",
+ "Top enabled: ": "Top aktiveret: ",
+ "CAPTCHA enabled: ": "CAPTCHA aktiveret: ",
+ "Login enabled: ": "Login aktiveret: ",
+ "Registration enabled: ": "Registrering aktiveret: ",
+ "Report statistics: ": "Indsend statistik: ",
+ "Save preferences": "Gem præferencer",
+ "Subscription manager": "Abonnementsmanager",
+ "Token manager": "Tokenmanager",
+ "Token": "Token",
"`x` subscriptions": {
- "([^.,0-9]|^)1([^.,0-9]|$)": "",
- "": ""
+ "([^.,0-9]|^)1([^.,0-9]|$)": "`x` abonnementer.([^.,0-9]|^)1([^.,0-9]|$)",
+ "": "`x`"
},
"`x` tokens": {
- "([^.,0-9]|^)1([^.,0-9]|$)": "",
- "": ""
+ "([^.,0-9]|^)1([^.,0-9]|$)": "`x` tokens.([^.,0-9]|^)1([^.,0-9]|$)",
+ "": "`x` tokens."
},
- "Import/export": "",
- "unsubscribe": "",
- "revoke": "",
- "Subscriptions": "",
+ "Import/export": "Importer/eksporter",
+ "unsubscribe": "opsig abonnement",
+ "revoke": "tilbagekald",
+ "Subscriptions": "Abonnementer",
"`x` unseen notifications": {
- "([^.,0-9]|^)1([^.,0-9]|$)": "",
- "": ""
+ "([^.,0-9]|^)1([^.,0-9]|$)": "`x` usete notifikationer.([^.,0-9]|^)1([^.,0-9]|$)",
+ "": "`x` usete notifikationer."
},
- "search": "",
- "Log out": "",
- "Released under the AGPLv3 by Omar Roth.": "",
- "Source available here.": "",
- "View JavaScript license information.": "",
- "View privacy policy.": "",
- "Trending": "",
- "Public": "",
- "Unlisted": "",
- "Private": "",
- "View all playlists": "",
+ "search": "søg",
+ "Log out": "Log ud",
+ "Released under the AGPLv3 by Omar Roth.": "Offentliggjort under AGPLv3 af Omar Roth.",
+ "Source available here.": "Kilde tilgængelig her.",
+ "View JavaScript license information.": "Vis JavaScriptlicensinformation.",
+ "View privacy policy.": "Vis privatpolitik.",
+ "Trending": "Trending",
+ "Public": "Offentlig",
+ "Unlisted": "Skjult",
+ "Private": "Privat",
+ "View all playlists": "Vis alle afspilningslister",
"Updated `x` ago": "",
- "Delete playlist `x`?": "",
- "Delete playlist": "",
- "Create playlist": "",
- "Title": "",
- "Playlist privacy": "",
- "Editing playlist `x`": "",
- "Watch on YouTube": "",
- "Hide annotations": "",
- "Show annotations": "",
- "Genre: ": "",
- "License: ": "",
- "Family friendly? ": "",
- "Wilson score: ": "",
- "Engagement: ": "",
- "Whitelisted regions: ": "",
- "Blacklisted regions: ": "",
- "Shared `x`": "",
+ "Delete playlist `x`?": "Opdateret `x` siden",
+ "Delete playlist": "Slet afspilningsliste",
+ "Create playlist": "Opret afspilningsliste",
+ "Title": "Titel",
+ "Playlist privacy": "Privatlivsindstillinger for afspilningsliste",
+ "Editing playlist `x`": "Redigerer afspilningsliste `x`",
+ "Watch on YouTube": "Se på YouTube",
+ "Hide annotations": "Skjul annotationer",
+ "Show annotations": "Vis annotationer",
+ "Genre: ": "Genre: ",
+ "License: ": "Licens: ",
+ "Family friendly? ": "Familievenlig? ",
+ "Wilson score: ": "Wilson score: ",
+ "Engagement: ": "Engagement: ",
+ "Whitelisted regions: ": "Whitelistede regioner: ",
+ "Blacklisted regions: ": "Blacklistede regioner: ",
+ "Shared `x`": "Delt `x`",
"`x` views": {
- "([^.,0-9]|^)1([^.,0-9]|$)": "",
- "": ""
+ "([^.,0-9]|^)1([^.,0-9]|$)": "`x` visninger.([^.,0-9]|^)1([^.,0-9]|$)",
+ "": "`x` visninger"
},
- "Premieres in `x`": "",
- "Premieres `x`": "",
- "Hi! Looks like you have JavaScript turned off. Click here to view comments, keep in mind they may take a bit longer to load.": "",
- "View YouTube comments": "",
- "View more comments on Reddit": "",
+ "Premieres in `x`": "Har premiere om `x`",
+ "Premieres `x`": "Har premiere om `x`",
+ "Hi! Looks like you have JavaScript turned off. Click here to view comments, keep in mind they may take a bit longer to load.": "Hej! Det ser ud til at du har JavaScript slået fra. Klik her for at se kommentarer, vær opmærksom på at de kan tage længere om at loade.",
+ "View YouTube comments": "Vis YouTube kommentarer",
+ "View more comments on Reddit": "Se flere kommentarer på Reddit",
"View `x` comments": {
- "([^.,0-9]|^)1([^.,0-9]|$)": "",
- "": ""
+ "([^.,0-9]|^)1([^.,0-9]|$)": "Vis `x` kommentarer.([^.,0-9]|^)1([^.,0-9]|$)",
+ "": "Vis `x` kommentarer."
},
- "View Reddit comments": "",
- "Hide replies": "",
- "Show replies": "",
- "Incorrect password": "",
- "Quota exceeded, try again in a few hours": "",
- "Unable to log in, make sure two-factor authentication (Authenticator or SMS) is turned on.": "",
+ "View Reddit comments": "Vis Reddit kommentarer",
+ "Hide replies": "Skjul svar",
+ "Show replies": "Vis svar",
+ "Incorrect password": "Forkert adgangskode",
+ "Quota exceeded, try again in a few hours": "Kvota overskredet, prøv igen om et par timer",
+ "Unable to log in, make sure two-factor authentication (Authenticator or SMS) is turned on.": "Login fejlet, tjek at totrinsbekræftelse (Authenticator eller SMS) er slået til.",
"Invalid TFA code": "",
"Login failed. This may be because two-factor authentication is not turned on for your account.": "",
"Wrong answer": "",
diff --git a/src/invidious.cr b/src/invidious.cr
index 88b9ad85..463a286a 100644
--- a/src/invidious.cr
+++ b/src/invidious.cr
@@ -308,9 +308,17 @@ end
Invidious::Routing.get "/", Invidious::Routes::Misc, :home
Invidious::Routing.get "/privacy", Invidious::Routes::Misc, :privacy
Invidious::Routing.get "/licenses", Invidious::Routes::Misc, :licenses
-Invidious::Routing.get "/watch", Invidious::Routes::Watch
+
+Invidious::Routing.get "/watch", Invidious::Routes::Watch, :handle
+Invidious::Routing.get "/watch/:id", Invidious::Routes::Watch, :redirect
+Invidious::Routing.get "/shorts/:id", Invidious::Routes::Watch, :redirect
+Invidious::Routing.get "/w/:id", Invidious::Routes::Watch, :redirect
+Invidious::Routing.get "/v/:id", Invidious::Routes::Watch, :redirect
+Invidious::Routing.get "/e/:id", Invidious::Routes::Watch, :redirect
+
Invidious::Routing.get "/embed/", Invidious::Routes::Embed, :redirect
Invidious::Routing.get "/embed/:id", Invidious::Routes::Embed, :show
+
Invidious::Routing.get "/view_all_playlists", Invidious::Routes::Playlists, :index
Invidious::Routing.get "/create_playlist", Invidious::Routes::Playlists, :new
Invidious::Routing.post "/create_playlist", Invidious::Routes::Playlists, :create
@@ -323,12 +331,15 @@ Invidious::Routing.get "/add_playlist_items", Invidious::Routes::Playlists, :add
Invidious::Routing.post "/playlist_ajax", Invidious::Routes::Playlists, :playlist_ajax
Invidious::Routing.get "/playlist", Invidious::Routes::Playlists, :show
Invidious::Routing.get "/mix", Invidious::Routes::Playlists, :mix
+
Invidious::Routing.get "/opensearch.xml", Invidious::Routes::Search, :opensearch
Invidious::Routing.get "/results", Invidious::Routes::Search, :results
Invidious::Routing.get "/search", Invidious::Routes::Search, :search
+
Invidious::Routing.get "/login", Invidious::Routes::Login, :login_page
Invidious::Routing.post "/login", Invidious::Routes::Login, :login
Invidious::Routing.post "/signout", Invidious::Routes::Login, :signout
+
Invidious::Routing.get "/preferences", Invidious::Routes::PreferencesRoute, :show
Invidious::Routing.post "/preferences", Invidious::Routes::PreferencesRoute, :update
Invidious::Routing.get "/toggle_theme", Invidious::Routes::PreferencesRoute, :toggle_theme
diff --git a/src/invidious/channels.cr b/src/invidious/channels.cr
index 47dfcbd6..3109b508 100644
--- a/src/invidious/channels.cr
+++ b/src/invidious/channels.cr
@@ -821,63 +821,87 @@ def get_about_info(ucid, locale)
raise ChannelRedirect.new(channel_id: browse_endpoint["browseId"].to_s)
end
- author = initdata["metadata"]["channelMetadataRenderer"]["title"].as_s
- author_url = initdata["metadata"]["channelMetadataRenderer"]["channelUrl"].as_s
- author_thumbnail = initdata["metadata"]["channelMetadataRenderer"]["avatar"]["thumbnails"][0]["url"].as_s
+ auto_generated = false
+ # Check for special auto generated gaming channels
+ if !initdata.has_key?("metadata")
+ auto_generated = true
+ end
+
+ if auto_generated
+ author = initdata["header"]["interactiveTabbedHeaderRenderer"]["title"]["simpleText"].as_s
+ author_url = initdata["microformat"]["microformatDataRenderer"]["urlCanonical"].as_s
+ author_thumbnail = initdata["header"]["interactiveTabbedHeaderRenderer"]["boxArt"]["thumbnails"][0]["url"].as_s
- ucid = initdata["metadata"]["channelMetadataRenderer"]["externalId"].as_s
+ # Raises a KeyError on failure.
+ banners = initdata["header"]["interactiveTabbedHeaderRenderer"]?.try &.["banner"]?.try &.["thumbnails"]?
+ banner = banners.try &.[-1]?.try &.["url"].as_s?
- # Raises a KeyError on failure.
- banners = initdata["header"]["c4TabbedHeaderRenderer"]?.try &.["banner"]?.try &.["thumbnails"]?
- banner = banners.try &.[-1]?.try &.["url"].as_s?
+ description = initdata["header"]["interactiveTabbedHeaderRenderer"]["description"]["simpleText"].as_s
+ description_html = HTML.escape(description).gsub("\n", "<br>")
- # if banner.includes? "channels/c4/default_banner"
- # banner = nil
- # end
+ paid = false
+ is_family_friendly = initdata["microformat"]["microformatDataRenderer"]["familySafe"].as_bool
+ allowed_regions = initdata["microformat"]["microformatDataRenderer"]["availableCountries"].as_a.map { |a| a.as_s }
- description = initdata["metadata"]["channelMetadataRenderer"]?.try &.["description"]?.try &.as_s? || ""
- description_html = HTML.escape(description).gsub("\n", "<br>")
+ related_channels = [] of AboutRelatedChannel
+ else
+ author = initdata["metadata"]["channelMetadataRenderer"]["title"].as_s
+ author_url = initdata["metadata"]["channelMetadataRenderer"]["channelUrl"].as_s
+ author_thumbnail = initdata["metadata"]["channelMetadataRenderer"]["avatar"]["thumbnails"][0]["url"].as_s
- paid = about.xpath_node(%q(//meta[@itemprop="paid"])).not_nil!["content"] == "True"
- is_family_friendly = about.xpath_node(%q(//meta[@itemprop="isFamilyFriendly"])).not_nil!["content"] == "True"
- allowed_regions = about.xpath_node(%q(//meta[@itemprop="regionsAllowed"])).not_nil!["content"].split(",")
+ ucid = initdata["metadata"]["channelMetadataRenderer"]["externalId"].as_s
- related_channels = initdata["contents"]["twoColumnBrowseResultsRenderer"]
- .["secondaryContents"]?.try &.["browseSecondaryContentsRenderer"]["contents"][0]?
- .try &.["verticalChannelSectionRenderer"]?.try &.["items"]?.try &.as_a.map do |node|
- renderer = node["miniChannelRenderer"]?
- related_id = renderer.try &.["channelId"]?.try &.as_s?
- related_id ||= ""
+ # Raises a KeyError on failure.
+ banners = initdata["header"]["c4TabbedHeaderRenderer"]?.try &.["banner"]?.try &.["thumbnails"]?
+ banner = banners.try &.[-1]?.try &.["url"].as_s?
- related_title = renderer.try &.["title"]?.try &.["simpleText"]?.try &.as_s?
- related_title ||= ""
+ # if banner.includes? "channels/c4/default_banner"
+ # banner = nil
+ # end
- related_author_url = renderer.try &.["navigationEndpoint"]?.try &.["commandMetadata"]?.try &.["webCommandMetadata"]?
- .try &.["url"]?.try &.as_s?
- related_author_url ||= ""
+ description = initdata["metadata"]["channelMetadataRenderer"]?.try &.["description"]?.try &.as_s? || ""
+ description_html = HTML.escape(description).gsub("\n", "<br>")
- related_author_thumbnails = renderer.try &.["thumbnail"]?.try &.["thumbnails"]?.try &.as_a?
- related_author_thumbnails ||= [] of JSON::Any
+ paid = about.xpath_node(%q(//meta[@itemprop="paid"])).not_nil!["content"] == "True"
+ is_family_friendly = about.xpath_node(%q(//meta[@itemprop="isFamilyFriendly"])).not_nil!["content"] == "True"
+ allowed_regions = about.xpath_node(%q(//meta[@itemprop="regionsAllowed"])).not_nil!["content"].split(",")
- related_author_thumbnail = ""
- if related_author_thumbnails.size > 0
- related_author_thumbnail = related_author_thumbnails[-1]["url"]?.try &.as_s?
- related_author_thumbnail ||= ""
- end
+ related_channels = initdata["contents"]["twoColumnBrowseResultsRenderer"]
+ .["secondaryContents"]?.try &.["browseSecondaryContentsRenderer"]["contents"][0]?
+ .try &.["verticalChannelSectionRenderer"]?.try &.["items"]?.try &.as_a.map do |node|
+ renderer = node["miniChannelRenderer"]?
+ related_id = renderer.try &.["channelId"]?.try &.as_s?
+ related_id ||= ""
- AboutRelatedChannel.new({
- ucid: related_id,
- author: related_title,
- author_url: related_author_url,
- author_thumbnail: related_author_thumbnail,
- })
- end
- related_channels ||= [] of AboutRelatedChannel
+ related_title = renderer.try &.["title"]?.try &.["simpleText"]?.try &.as_s?
+ related_title ||= ""
+
+ related_author_url = renderer.try &.["navigationEndpoint"]?.try &.["commandMetadata"]?.try &.["webCommandMetadata"]?
+ .try &.["url"]?.try &.as_s?
+ related_author_url ||= ""
+
+ related_author_thumbnails = renderer.try &.["thumbnail"]?.try &.["thumbnails"]?.try &.as_a?
+ related_author_thumbnails ||= [] of JSON::Any
+
+ related_author_thumbnail = ""
+ if related_author_thumbnails.size > 0
+ related_author_thumbnail = related_author_thumbnails[-1]["url"]?.try &.as_s?
+ related_author_thumbnail ||= ""
+ end
+
+ AboutRelatedChannel.new({
+ ucid: related_id,
+ author: related_title,
+ author_url: related_author_url,
+ author_thumbnail: related_author_thumbnail,
+ })
+ end
+ related_channels ||= [] of AboutRelatedChannel
+ end
total_views = 0_i64
joined = Time.unix(0)
tabs = [] of String
- auto_generated = false
tabs_json = initdata["contents"]["twoColumnBrowseResultsRenderer"]["tabs"]?.try &.as_a?
if !tabs_json.nil?
@@ -895,7 +919,7 @@ def get_about_info(ucid, locale)
joined = channel_about_meta["joinedDateText"]?.try &.["runs"]?.try &.as_a.reduce("") { |acc, node| acc + node["text"].as_s }
.try { |text| Time.parse(text, "Joined %b %-d, %Y", Time::Location.local) } || Time.unix(0)
- # Auto-generated channels
+ # Normal Auto-generated channels
# https://support.google.com/youtube/answer/2579942
# For auto-generated channels, channel_about_meta only has ["description"]["simpleText"] and ["primaryLinks"][0]["title"]["simpleText"]
if (channel_about_meta["primaryLinks"]?.try &.size || 0) == 1 && (channel_about_meta["primaryLinks"][0]?) &&
diff --git a/src/invidious/helpers/helpers.cr b/src/invidious/helpers/helpers.cr
index 5d127e1a..f6b6acd1 100644
--- a/src/invidious/helpers/helpers.cr
+++ b/src/invidious/helpers/helpers.cr
@@ -42,7 +42,7 @@ struct ConfigPreferences
property player_style : String = "invidious"
property quality : String = "hd720"
property quality_dash : String = "auto"
- property default_home : String = "Popular"
+ property default_home : String? = "Popular"
property feed_menu : Array(String) = ["Popular", "Trending", "Subscriptions", "Playlists"]
property related_videos : Bool = true
property sort : String = "published"
diff --git a/src/invidious/jobs/statistics_refresh_job.cr b/src/invidious/jobs/statistics_refresh_job.cr
index aa46fb0e..6569c0a1 100644
--- a/src/invidious/jobs/statistics_refresh_job.cr
+++ b/src/invidious/jobs/statistics_refresh_job.cr
@@ -42,7 +42,7 @@ class Invidious::Jobs::StatisticsRefreshJob < Invidious::Jobs::BaseJob
"version" => @software_config["version"],
"branch" => @software_config["branch"],
}
- STATISTICS["openRegistration"] = CONFIG.registration_enabled
+ STATISTICS["openRegistrations"] = CONFIG.registration_enabled
end
private def refresh_stats
diff --git a/src/invidious/playlists.cr b/src/invidious/playlists.cr
index 71f6a9b8..073a9986 100644
--- a/src/invidious/playlists.cr
+++ b/src/invidious/playlists.cr
@@ -437,7 +437,8 @@ end
def get_playlist_videos(db, playlist, offset, locale = nil, continuation = nil)
# Show empy playlist if requested page is out of range
- if offset >= playlist.video_count
+ # (e.g, when a new playlist has been created, offset will be negative)
+ if offset >= playlist.video_count || offset < 0
return [] of PlaylistVideo
end
diff --git a/src/invidious/routes/watch.cr b/src/invidious/routes/watch.cr
index 8169e1ed..d0338882 100644
--- a/src/invidious/routes/watch.cr
+++ b/src/invidious/routes/watch.cr
@@ -187,4 +187,13 @@ class Invidious::Routes::Watch < Invidious::Routes::BaseRoute
templated "watch"
end
+
+ def redirect(env)
+ url = "/watch?v=#{env.params.url["id"]}"
+ if env.params.query.size > 0
+ url += "&#{env.params.query}"
+ end
+
+ return env.redirect url
+ end
end
diff --git a/src/invidious/users.cr b/src/invidious/users.cr
index 7a948b76..8fef64a0 100644
--- a/src/invidious/users.cr
+++ b/src/invidious/users.cr
@@ -68,7 +68,7 @@ struct Preferences
property quality : String = CONFIG.default_user_preferences.quality
@[JSON::Field(converter: Preferences::ProcessString)]
property quality_dash : String = CONFIG.default_user_preferences.quality_dash
- property default_home : String = CONFIG.default_user_preferences.default_home
+ property default_home : String? = CONFIG.default_user_preferences.default_home
property feed_menu : Array(String) = CONFIG.default_user_preferences.feed_menu
property related_videos : Bool = CONFIG.default_user_preferences.related_videos
diff --git a/src/invidious/videos.cr b/src/invidious/videos.cr
index e6d4c764..38646311 100644
--- a/src/invidious/videos.cr
+++ b/src/invidious/videos.cr
@@ -1150,15 +1150,15 @@ end
def build_thumbnails(id)
return {
- {name: "maxres", host: "#{HOST_URL}", url: "maxres", height: 720, width: 1280},
- {name: "maxresdefault", host: "https://i.ytimg.com", url: "maxresdefault", height: 720, width: 1280},
- {name: "sddefault", host: "https://i.ytimg.com", url: "sddefault", height: 480, width: 640},
- {name: "high", host: "https://i.ytimg.com", url: "hqdefault", height: 360, width: 480},
- {name: "medium", host: "https://i.ytimg.com", url: "mqdefault", height: 180, width: 320},
- {name: "default", host: "https://i.ytimg.com", url: "default", height: 90, width: 120},
- {name: "start", host: "https://i.ytimg.com", url: "1", height: 90, width: 120},
- {name: "middle", host: "https://i.ytimg.com", url: "2", height: 90, width: 120},
- {name: "end", host: "https://i.ytimg.com", url: "3", height: 90, width: 120},
+ {host: HOST_URL, height: 720, width: 1280, name: "maxres", url: "maxres"},
+ {host: HOST_URL, height: 720, width: 1280, name: "maxresdefault", url: "maxresdefault"},
+ {host: HOST_URL, height: 480, width: 640, name: "sddefault", url: "sddefault"},
+ {host: HOST_URL, height: 360, width: 480, name: "high", url: "hqdefault"},
+ {host: HOST_URL, height: 180, width: 320, name: "medium", url: "mqdefault"},
+ {host: HOST_URL, height: 90, width: 120, name: "default", url: "default"},
+ {host: HOST_URL, height: 90, width: 120, name: "start", url: "1"},
+ {host: HOST_URL, height: 90, width: 120, name: "middle", url: "2"},
+ {host: HOST_URL, height: 90, width: 120, name: "end", url: "3"},
}
end
diff --git a/src/invidious/views/template.ecr b/src/invidious/views/template.ecr
index 33638055..5b63bf1f 100644
--- a/src/invidious/views/template.ecr
+++ b/src/invidious/views/template.ecr
@@ -26,7 +26,7 @@
<span style="display:none" id="dark_mode_pref"><%= env.get("preferences").as(Preferences).dark_mode %></span>
<div class="pure-g">
<div class="pure-u-1 pure-u-md-2-24"></div>
- <div class="pure-u-1 pure-u-md-20-24">
+ <div class="pure-u-1 pure-u-md-20-24", id="contents">
<div class="pure-g navbar h-box">
<% if navbar_search %>
<div class="pure-u-1 pure-u-md-4-24">
@@ -109,7 +109,7 @@
<%= content %>
- <div class="footer">
+ <footer>
<div class="pure-g">
<div class="pure-u-1 pure-u-md-1-3">
<a href="https://github.com/iv-org/invidious">
@@ -143,7 +143,7 @@
<%= translate(locale, "Current version: ") %> <%= CURRENT_VERSION %>-<%= CURRENT_COMMIT %> @ <%= CURRENT_BRANCH %>
</div>
</div>
- </div>
+ </footer>
</div>
<div class="pure-u-1 pure-u-md-2-24"></div>
</div>