From bdbc7f6c42bc9a113230b6e0113b8641d511d3d5 Mon Sep 17 00:00:00 2001 From: Kayra Uylar <52961639+kuylar@users.noreply.github.com> Date: Tue, 9 Apr 2024 17:49:07 +0300 Subject: [PATCH] Make configs better (#129) * Update /api/info to be more extensible * Parse configs at startup * Make the error page respect user's theme * Delete obsolete code * Bump API version * Formatting, and change how LIGHTTUBE_MOTD works * Implement the alert in the page layout --- LightTube/ApiModels/LightTubeInstanceInfo.cs | 8 +- .../Attributes/ApiDisableableAttribute.cs | 2 +- .../OauthApiDisableableAttribute.cs | 2 +- LightTube/Configuration.cs | 96 ++++++++++++------- LightTube/Contexts/BaseContext.cs | 9 +- LightTube/Contexts/PlayerContext.cs | 2 +- LightTube/Controllers/AccountController.cs | 2 +- LightTube/Controllers/ApiController.cs | 17 ++-- LightTube/Controllers/HomeController.cs | 26 +++-- LightTube/Controllers/MediaController.cs | 14 +-- LightTube/Controllers/OAuth2Controller.cs | 6 +- LightTube/Controllers/SettingsController.cs | 2 +- LightTube/Controllers/TogglesController.cs | 22 ----- LightTube/Database/DatabaseManager.cs | 2 +- LightTube/JsCache.cs | 9 +- LightTube/Program.cs | 7 +- LightTube/Utils.cs | 25 ++++- LightTube/Views/Account/Register.cshtml | 2 +- LightTube/Views/Home/Error.cshtml | 6 +- LightTube/Views/Home/Index.cshtml | 32 +++---- LightTube/Views/Shared/Player.cshtml | 4 +- LightTube/Views/Shared/_Layout.cshtml | 16 +++- LightTube/Views/Shared/_ModalLayout.cshtml | 2 +- LightTube/Views/Shared/_SettingsLayout.cshtml | 2 +- LightTube/wwwroot/css/lighttube.css | 19 ++++ 25 files changed, 194 insertions(+), 140 deletions(-) delete mode 100644 LightTube/Controllers/TogglesController.cs diff --git a/LightTube/ApiModels/LightTubeInstanceInfo.cs b/LightTube/ApiModels/LightTubeInstanceInfo.cs index ba1ab561..771754bc 100644 --- a/LightTube/ApiModels/LightTubeInstanceInfo.cs +++ b/LightTube/ApiModels/LightTubeInstanceInfo.cs @@ -6,9 +6,7 @@ public class LightTubeInstanceInfo { [JsonProperty("type")] public string Type { get; set; } [JsonProperty("version")] public string Version { get; set; } - [JsonProperty("motd")] public string Motd { get; set; } - [JsonProperty("allowsApi")] public bool AllowsApi { get; set; } - [JsonProperty("allowsNewUsers")] public bool AllowsNewUsers { get; set; } - [JsonProperty("allowsOauthApi")] public bool AllowsOauthApi { get; set; } - [JsonProperty("allowsThirdPartyProxyUsage")] public bool AllowsThirdPartyProxyUsage { get; set; } + [JsonProperty("motd")] public string[] Messages { get; set; } + [JsonProperty("alert")] public string? Alert { get; set; } + [JsonProperty("config")] public Dictionary Config { get; set; } } \ No newline at end of file diff --git a/LightTube/Attributes/ApiDisableableAttribute.cs b/LightTube/Attributes/ApiDisableableAttribute.cs index 78600574..03157dd6 100644 --- a/LightTube/Attributes/ApiDisableableAttribute.cs +++ b/LightTube/Attributes/ApiDisableableAttribute.cs @@ -17,7 +17,7 @@ public ApiDisableableAttribute(params string[] scopes) public void OnActionExecuting(ActionExecutingContext context) { - if (Configuration.GetVariable("LIGHTTUBE_DISABLE_API", "")?.ToLower() != "true") return; + if (Configuration.ApiEnabled) return; context.HttpContext.Response.StatusCode = (int)HttpStatusCode.Unauthorized; context.Result = new ContentResult(); } diff --git a/LightTube/Attributes/OauthApiDisableableAttribute.cs b/LightTube/Attributes/OauthApiDisableableAttribute.cs index 147eae30..bb66747b 100644 --- a/LightTube/Attributes/OauthApiDisableableAttribute.cs +++ b/LightTube/Attributes/OauthApiDisableableAttribute.cs @@ -17,7 +17,7 @@ public OauthApiDisableableAttribute(params string[] scopes) public void OnActionExecuting(ActionExecutingContext context) { - if (Configuration.GetVariable("LIGHTTUBE_DISABLE_OAUTH", "")?.ToLower() != "true") return; + if (Configuration.OauthEnabled) return; context.HttpContext.Response.StatusCode = (int)HttpStatusCode.Unauthorized; context.Result = new ContentResult(); } diff --git a/LightTube/Configuration.cs b/LightTube/Configuration.cs index 64ff3c6a..6701b698 100644 --- a/LightTube/Configuration.cs +++ b/LightTube/Configuration.cs @@ -1,62 +1,90 @@ using System.Text.RegularExpressions; using InnerTube; +using Newtonsoft.Json; namespace LightTube; public static class Configuration { - private static Dictionary _variables = new(); - private static Dictionary _customThemeDefs = null; + public static Dictionary CustomThemeDefs { get; } = new(); + public static InnerTubeAuthorization? InnerTubeAuthorization { get; private set; } + public static bool ApiEnabled { get; private set; } + public static bool OauthEnabled { get; private set; } + public static bool RegistrationEnabled { get; private set; } + public static bool ProxyEnabled { get; private set; } + public static bool ThirdPartyProxyEnabled { get; private set; } + public static int CacheSize { get; private set; } + public static string ConnectionString { get; private set; } + public static string Database { get; private set; } + public static string DefaultContentLanguage { get; private set; } = "en"; + public static string DefaultContentRegion { get; private set; } = "US"; + public static string DefaultTheme { get; private set; } = "auto"; + public static string? CustomCssPath { get; private set; } + public static string[] Messages { get; private set; } + public static string? Alert { get; private set; } + public static string? AlertHash { get; private set; } + private static Random random = new(); - public static string? GetVariable(string var, string? def = null) + private static string? GetVariable(string var, string? def = null) => + Environment.GetEnvironmentVariable(var) ?? def; + + public static void InitConfig() { - if (_variables.TryGetValue(var, out string? res)) return res; - string? v = Environment.GetEnvironmentVariable(var) ?? def; - if (v == null) return null; - _variables.Add(var, v); - return v; - } - - public static InnerTubeAuthorization? GetInnerTubeAuthorization() => - GetVariable("LIGHTTUBE_AUTH_TYPE")?.ToLower() switch + InnerTubeAuthorization = Environment.GetEnvironmentVariable("LIGHTTUBE_AUTH_TYPE")?.ToLower() switch { "cookie" => InnerTubeAuthorization.SapisidAuthorization( - GetVariable("LIGHTTUBE_AUTH_SAPISID") ?? + Environment.GetEnvironmentVariable("LIGHTTUBE_AUTH_SAPISID") ?? throw new ArgumentNullException("LIGHTTUBE_AUTH_SAPISID", "Authentication type set to 'cookie' but the 'LIGHTTUBE_AUTH_SAPISID' environment variable is not set."), - GetVariable("LIGHTTUBE_AUTH_PSID") ?? + Environment.GetEnvironmentVariable("LIGHTTUBE_AUTH_PSID") ?? throw new ArgumentNullException("LIGHTTUBE_AUTH_PSID", "Authentication type set to 'cookie' but the 'LIGHTTUBE_AUTH_PSID' environment variable is not set.")), "oauth2" => InnerTubeAuthorization.RefreshTokenAuthorization( - GetVariable("LIGHTTUBE_AUTH_REFRESH_TOKEN") ?? + Environment.GetEnvironmentVariable("LIGHTTUBE_AUTH_REFRESH_TOKEN") ?? throw new ArgumentNullException("LIGHTTUBE_AUTH_REFRESH_TOKEN", "Authentication type set to 'oauth2' but the 'LIGHTTUBE_AUTH_REFRESH_TOKEN' environment variable is not set.")), - var _ => null + _ => null }; - public static Dictionary GetCustomThemeDefs() - { - if (_customThemeDefs == null) + CustomCssPath = Environment.GetEnvironmentVariable("LIGHTTUBE_CUSTOM_CSS_PATH"); + if (CustomCssPath != null) { - Dictionary dict = new(); - string? fileName = GetVariable("LIGHTTUBE_CUSTOM_CSS_PATH"); - - if (fileName != null) + string contents = File.ReadAllText(CustomCssPath); + MatchCollection matches = Regex.Matches(contents, "@themedef \"(.+?)\" (\\S+)"); + foreach (Match match in matches) { - using FileStream fs = File.OpenRead(fileName); - using StreamReader sr = new(fs); - string contents = sr.ReadToEnd(); - fs.Close(); - MatchCollection matches = Regex.Matches(contents, "@themedef \"(.+?)\" (\\S+)"); - foreach (Match match in matches) - { - dict.Add(match.Groups[2].Value, match.Groups[1].Value); - } + CustomThemeDefs.Add(match.Groups[2].Value, match.Groups[1].Value); } + } + + ApiEnabled = GetVariable("LIGHTTUBE_DISABLE_API", "false")?.ToLower() != "true"; + OauthEnabled = GetVariable("LIGHTTUBE_DISABLE_OAUTH", "false")?.ToLower() != "true"; + RegistrationEnabled = GetVariable("LIGHTTUBE_DISABLE_REGISTRATION", "false")?.ToLower() != "true"; + ProxyEnabled = GetVariable("LIGHTTUBE_DISABLE_PROXY", "false")?.ToLower() != "true"; + ThirdPartyProxyEnabled = GetVariable("LIGHTTUBE_ENABLE_THIRD_PARTY_PROXY", "false")?.ToLower() != "true" && ProxyEnabled; - _customThemeDefs = dict; + CacheSize = int.Parse(GetVariable("LIGHTTUBE_CACHE_SIZE", "50")!); + ConnectionString = GetVariable("LIGHTTUBE_MONGODB_CONNSTR") ?? throw new ArgumentNullException( + "LIGHTTUBE_MONGODB_CONNSTR", + "Database connection string is not set. Please set the 'LIGHTTUBE_MONGODB_CONNSTR' to a valid MongoDB connection string."); + Database = GetVariable("LIGHTTUBE_MONGODB_DATABASE", "lighttube")!; + DefaultContentLanguage = GetVariable("LIGHTTUBE_DEFAULT_CONTENT_LANGUAGE", "en")!; + DefaultContentRegion = GetVariable("LIGHTTUBE_DEFAULT_CONTENT_REGION", "US")!; + DefaultTheme = GetVariable("LIGHTTUBE_DEFAULT_THEME", "auto")!; + + try + { + Messages = JsonConvert.DeserializeObject(GetVariable("LIGHTTUBE_MOTD", + "[\"Search something to get started!\"]")!)!; + } + catch (Exception) + { + Messages = new[] { "Search something to get started!" }; } - return _customThemeDefs; + Alert = GetVariable("LIGHTTUBE_ALERT") ?? ":3 check! press the X to :3"; + AlertHash = Alert != null ? Utils.Md5Sum(Alert) : null; } + + public static string RandomMessage() => Messages[random.Next(0, Messages.Length)]; } \ No newline at end of file diff --git a/LightTube/Contexts/BaseContext.cs b/LightTube/Contexts/BaseContext.cs index 25a092a5..f2a001aa 100644 --- a/LightTube/Contexts/BaseContext.cs +++ b/LightTube/Contexts/BaseContext.cs @@ -62,15 +62,8 @@ public void AddMeta(string property, string content) return Context.Request.Cookies.TryGetValue("lastSearch", out string? q) ? q : null; } - [Obsolete("Use GetThemClass instead")] - public bool IsDarkMode() - { - if (Context.Request.Cookies.TryGetValue("theme", out string? theme)) return theme == "dark"; - return Configuration.GetVariable("LIGHTTUBE_DEFAULT_THEME", "light") == "dark"; - } - public string GetThemeClass() => Context.Request.Cookies.TryGetValue("theme", out string? theme) ? $"theme-{theme}" - : $"theme-{Configuration.GetVariable("LIGHTTUBE_DEFAULT_THEME", "auto")}"; + : $"theme-{Configuration.DefaultTheme}"; } \ No newline at end of file diff --git a/LightTube/Contexts/PlayerContext.cs b/LightTube/Contexts/PlayerContext.cs index 33b04ef1..0d89e1ad 100644 --- a/LightTube/Contexts/PlayerContext.cs +++ b/LightTube/Contexts/PlayerContext.cs @@ -30,7 +30,7 @@ public PlayerContext(HttpContext context, InnerTubePlayer innerTubePlayer, Inner UseHls = !compatibility; // Prefer HLS UseDash = innerTubePlayer.AdaptiveFormats.Any() && !compatibility; // Formats - if (Configuration.GetVariable("LIGHTTUBE_DISABLE_PROXY", "false") != "false") + if (!Configuration.ProxyEnabled) { UseHls = false; UseDash = false; diff --git a/LightTube/Controllers/AccountController.cs b/LightTube/Controllers/AccountController.cs index 2d8d9f8a..302826f8 100644 --- a/LightTube/Controllers/AccountController.cs +++ b/LightTube/Controllers/AccountController.cs @@ -27,7 +27,7 @@ public async Task Register(string? redirectUrl, string userId, st UserID = userId }; - if (Configuration.GetVariable("LIGHTTUBE_DISABLE_REGISTRATION", "false") != "false") + if (!Configuration.RegistrationEnabled) return View(ac); if (userId is null || password is null || passwordCheck is null) diff --git a/LightTube/Controllers/ApiController.cs b/LightTube/Controllers/ApiController.cs index d90d99ef..82e8f2ed 100644 --- a/LightTube/Controllers/ApiController.cs +++ b/LightTube/Controllers/ApiController.cs @@ -26,14 +26,17 @@ public ApiController(InnerTube.InnerTube youtube) public LightTubeInstanceInfo GetInstanceInfo() => new() { - Type = "lighttube", + Type = "lighttube/2.0", Version = Utils.GetVersion(), - Motd = Configuration.GetVariable("LIGHTTUBE_MOTD", "Search something to get started!")!, - AllowsApi = Configuration.GetVariable("LIGHTTUBE_DISABLE_API", "")?.ToLower() != "true", - AllowsNewUsers = Configuration.GetVariable("LIGHTTUBE_DISABLE_REGISTRATION", "")?.ToLower() != "true", - AllowsOauthApi = Configuration.GetVariable("LIGHTTUBE_DISABLE_OAUTH", "")?.ToLower() != "true", - AllowsThirdPartyProxyUsage = - Configuration.GetVariable("LIGHTTUBE_ENABLE_THIRD_PARTY_PROXY", "false")?.ToLower() == "true" + Messages = Configuration.Messages, + Alert = Configuration.Alert, + Config = new Dictionary + { + ["allowsApi"] = Configuration.ApiEnabled, + ["allowsNewUsers"] = Configuration.RegistrationEnabled, + ["allowsOauthApi"] = Configuration.OauthEnabled, + ["allowsThirdPartyProxyUsage"] = Configuration.ThirdPartyProxyEnabled + } }; private ApiResponse Error(string message, int code, HttpStatusCode statusCode) diff --git a/LightTube/Controllers/HomeController.cs b/LightTube/Controllers/HomeController.cs index 209f851b..825ef639 100644 --- a/LightTube/Controllers/HomeController.cs +++ b/LightTube/Controllers/HomeController.cs @@ -2,6 +2,7 @@ using LightTube.Contexts; using Microsoft.AspNetCore.Mvc; using Microsoft.Net.Http.Headers; +using SameSiteMode = Microsoft.AspNetCore.Http.SameSiteMode; namespace LightTube.Controllers; @@ -25,18 +26,12 @@ public HomeController(ILogger logger) [Route("/css/custom.css")] public IActionResult CustomCss() { - string? fileName = Configuration.GetVariable("LIGHTTUBE_CUSTOM_CSS_PATH"); + string? fileName = Configuration.CustomCssPath; - if (fileName != null) - { - using FileStream fs = System.IO.File.OpenRead(fileName); - using StreamReader sr = new(fs); - string contents = sr.ReadToEnd(); - fs.Close(); - return File(Encoding.UTF8.GetBytes(contents), "text/css"); - } + if (fileName == null) return NotFound(); - return NotFound(); + using FileStream fs = System.IO.File.OpenRead(fileName); + return File(fs, "text/css"); } [Route("/lib/{name}")] @@ -53,4 +48,15 @@ public IActionResult CachedJs(string name) return NotFound(); } } + + [Route("/dismiss_alert")] + public IActionResult DismissAlert(string redirectUrl) + { + if (Configuration.AlertHash == null) return Redirect(redirectUrl); + Response.Cookies.Append("dismissedAlert", Configuration.AlertHash!, new CookieOptions + { + Expires = DateTimeOffset.UtcNow.AddDays(15) + }); + return Redirect(redirectUrl); + } } \ No newline at end of file diff --git a/LightTube/Controllers/MediaController.cs b/LightTube/Controllers/MediaController.cs index 2cbea57c..7c95976e 100644 --- a/LightTube/Controllers/MediaController.cs +++ b/LightTube/Controllers/MediaController.cs @@ -40,7 +40,7 @@ public ProxyController(InnerTube.InnerTube youtube) [Route("media/{videoId}/{formatId}.{extension}")] public async Task Media(string videoId, string formatId, string? audioTrackId, string? extension = null) { - if (Configuration.GetVariable("LIGHTTUBE_DISABLE_PROXY", "false") != "false") + if (!Configuration.ProxyEnabled) { Response.StatusCode = (int)HttpStatusCode.NotFound; await Response.Body.WriteAsync(Encoding.UTF8.GetBytes("This instance has disabled media proxies.")); @@ -133,7 +133,7 @@ await Response.Body.WriteAsync(Encoding.UTF8.GetBytes( public async Task HlsProxy(string videoId, string formatId, bool useProxy = true, bool skipCaptions = false) { - if (Configuration.GetVariable("LIGHTTUBE_DISABLE_PROXY", "false") != "false") + if (!Configuration.ProxyEnabled) useProxy = false; try @@ -170,7 +170,7 @@ public async Task HlsProxy(string videoId, string formatId, bool public async Task DashProxy(string videoId, string formatId, bool useProxy = true, bool skipCaptions = false) { - if (Configuration.GetVariable("LIGHTTUBE_DISABLE_PROXY", "false") != "false") + if (!Configuration.ProxyEnabled) useProxy = false; try @@ -196,7 +196,7 @@ public async Task DashProxy(string videoId, string formatId, bool [Route("hls/playlist/{path}")] public async Task HlsPlaylistProxy(string path, bool useProxy = true) { - if (Configuration.GetVariable("LIGHTTUBE_DISABLE_PROXY", "false") != "false") + if (!Configuration.ProxyEnabled) return NotFound("This instance has disabled media proxies."); try @@ -222,7 +222,7 @@ public async Task HlsPlaylistProxy(string path, bool useProxy = t [Route("hls/timedtext/{path}")] public async Task HlsSubtitleProxy(string path, bool useProxy = true) { - if (Configuration.GetVariable("LIGHTTUBE_DISABLE_PROXY", "false") != "false") + if (!Configuration.ProxyEnabled) return NotFound("This instance has disabled media proxies."); try @@ -248,7 +248,7 @@ public async Task HlsSubtitleProxy(string path, bool useProxy = t [Route("hls/segment/{path}")] public async Task HlsSegmentProxy(string path) { - if (Configuration.GetVariable("LIGHTTUBE_DISABLE_PROXY", "false") != "false") + if (!Configuration.ProxyEnabled) { Response.StatusCode = (int)HttpStatusCode.NotFound; await Response.Body.WriteAsync(Encoding.UTF8.GetBytes("This instance has disabled media proxies.")); @@ -359,7 +359,7 @@ public async Task SubtitleProxy(string videoId, string vssId) [Route("thumbnail/{videoId}/{index:int}")] public async Task ThumbnailProxy(string videoId, int index = 0) { - if (Configuration.GetVariable("LIGHTTUBE_DISABLE_PROXY", "false") != "false") + if (!Configuration.ProxyEnabled) { Response.StatusCode = (int)HttpStatusCode.NotFound; await Response.Body.WriteAsync(Encoding.UTF8.GetBytes("This instance has disabled media proxies.")); diff --git a/LightTube/Controllers/OAuth2Controller.cs b/LightTube/Controllers/OAuth2Controller.cs index c5d7c986..b7c21e09 100644 --- a/LightTube/Controllers/OAuth2Controller.cs +++ b/LightTube/Controllers/OAuth2Controller.cs @@ -21,7 +21,7 @@ public async Task Authorize( [FromQuery(Name = "scope")] string? scope, [FromQuery(Name = "state")] string? state = null) { - if (Configuration.GetVariable("LIGHTTUBE_DISABLE_OAUTH", "")?.ToLower() == "true") + if (!Configuration.OauthEnabled) return View(new OAuthContext("This instance does not allow OAuth2")); if (string.IsNullOrEmpty(responseType)) return View(new OAuthContext("response_type cannot be empty")); @@ -66,7 +66,7 @@ public async Task GetAuthTokenAndRedirect( [FromQuery(Name = "scope")] string scope, [FromQuery(Name = "state")] string? state = null) { - if (Configuration.GetVariable("LIGHTTUBE_DISABLE_OAUTH", "")?.ToLower() == "true") + if (!Configuration.OauthEnabled) throw new Exception("Instance doesn't allow OAuth"); if (string.IsNullOrEmpty(responseType)) @@ -122,7 +122,7 @@ public async Task GrantTokenAsync( [FromForm(Name = "client_id")] string clientId, [FromForm(Name = "client_secret")] string clientSecret) { - if (Configuration.GetVariable("LIGHTTUBE_DISABLE_OAUTH", "")?.ToLower() == "true") + if (!Configuration.OauthEnabled) return Unauthorized(); if (grantType is not ("code" or "authorization_code" or "refresh_token")) return Unauthorized(); diff --git a/LightTube/Controllers/SettingsController.cs b/LightTube/Controllers/SettingsController.cs index aaf4a421..7997441c 100644 --- a/LightTube/Controllers/SettingsController.cs +++ b/LightTube/Controllers/SettingsController.cs @@ -29,7 +29,7 @@ public SettingsController(InnerTube.InnerTube youtube) public async Task Appearance() { InnerTubeLocals locals = await _youtube.GetLocalsAsync(); - AppearanceSettingsContext ctx = new(HttpContext, locals, Configuration.GetCustomThemeDefs()); + AppearanceSettingsContext ctx = new(HttpContext, locals, Configuration.CustomThemeDefs); return View(ctx); } diff --git a/LightTube/Controllers/TogglesController.cs b/LightTube/Controllers/TogglesController.cs deleted file mode 100644 index 9b4890f8..00000000 --- a/LightTube/Controllers/TogglesController.cs +++ /dev/null @@ -1,22 +0,0 @@ -using LightTube.Contexts; -using Microsoft.AspNetCore.Mvc; - -namespace LightTube.Controllers; - -[Route("/toggles")] -public class TogglesController : Controller -{ - [Route("theme")] - public IActionResult ToggleTheme(string url) - { - BaseContext bc = new(HttpContext); - string newTheme = bc.IsDarkMode() ? "light" : "dark"; - - HttpContext.Response.Cookies.Append("theme", newTheme, new CookieOptions - { - Expires = DateTimeOffset.MaxValue - }); - - return Redirect(url); - } -} \ No newline at end of file diff --git a/LightTube/Database/DatabaseManager.cs b/LightTube/Database/DatabaseManager.cs index 7d4ab59a..21daf790 100644 --- a/LightTube/Database/DatabaseManager.cs +++ b/LightTube/Database/DatabaseManager.cs @@ -21,7 +21,7 @@ public static class DatabaseManager public static void Init(string connstr) { MongoClient client = new(connstr); - Database = client.GetDatabase(Configuration.GetVariable("LIGHTTUBE_MONGODB_DATABASE", "lighttube")); + Database = client.GetDatabase(Configuration.Database); UserCollection = Database.GetCollection("users"); TokensCollection = Database.GetCollection("tokens"); VideoCacheCollection = Database.GetCollection("videoCache"); diff --git a/LightTube/JsCache.cs b/LightTube/JsCache.cs index f0ba8c0a..65c30727 100644 --- a/LightTube/JsCache.cs +++ b/LightTube/JsCache.cs @@ -1,5 +1,3 @@ -using System.Security.Cryptography; -using System.Text; using System.Web; using Serilog; @@ -29,13 +27,8 @@ public static async Task DownloadLibraries() string jsData = await response.Content.ReadAsStringAsync(); await File.WriteAllTextAsync($"/tmp/lighttube/jsCache/{name}", jsData); Log.Debug($"[JsCache] Calculating the MD5 hash of {name}..."); - - using MD5 md5 = MD5.Create(); - byte[] inputBytes = Encoding.ASCII.GetBytes(jsData); - byte[] hashBytes = md5.ComputeHash(inputBytes); - string hash = Convert.ToHexString(hashBytes); - Hashes[name] = hash; + Hashes[name] = Utils.Md5Sum(jsData); Log.Information($"[JsCache] Downloaded '{name}'."); } diff --git a/LightTube/Program.cs b/LightTube/Program.cs index 3dc7d2ff..e0def6a2 100644 --- a/LightTube/Program.cs +++ b/LightTube/Program.cs @@ -13,6 +13,7 @@ .WriteTo.Console() .CreateBootstrapLogger(); +Configuration.InitConfig(); try { WebApplicationBuilder builder = WebApplication.CreateBuilder(args); @@ -26,18 +27,18 @@ // Add services to the container. builder.Services.AddControllersWithViews().AddNewtonsoftJson(); - InnerTubeAuthorization? auth = Configuration.GetInnerTubeAuthorization(); + InnerTubeAuthorization? auth = Configuration.InnerTubeAuthorization; builder.Services.AddSingleton(new InnerTube.InnerTube(new InnerTubeConfiguration { Authorization = auth, - CacheSize = int.Parse(Configuration.GetVariable("LIGHTTUBE_CACHE_SIZE", "50")!), + CacheSize = Configuration.CacheSize, CacheExpirationPollingInterval = default })); builder.Services.AddSingleton(new HttpClient()); await JsCache.DownloadLibraries(); ChoreManager.RegisterChores(); - DatabaseManager.Init(Configuration.GetVariable("LIGHTTUBE_MONGODB_CONNSTR")); + DatabaseManager.Init(Configuration.ConnectionString); WebApplication app = builder.Build(); diff --git a/LightTube/Utils.cs b/LightTube/Utils.cs index a8f75c25..829124de 100644 --- a/LightTube/Utils.cs +++ b/LightTube/Utils.cs @@ -3,6 +3,7 @@ using System.Globalization; using System.Net; using System.Reflection; +using System.Security.Cryptography; using System.Text; using System.Web; using System.Xml; @@ -32,14 +33,14 @@ public static string GetRegion(this HttpContext context) => ? h.ToString() : context.Request.Cookies.TryGetValue("gl", out string region) ? region - : Configuration.GetVariable("LIGHTTUBE_DEFAULT_CONTENT_REGION", "US"); + : Configuration.DefaultContentRegion; public static string GetLanguage(this HttpContext context) => context.Request.Headers.TryGetValue("X-Content-Language", out StringValues h) ? h.ToString() : context.Request.Cookies.TryGetValue("hl", out string language) ? language - : Configuration.GetVariable("LIGHTTUBE_DEFAULT_CONTENT_LANGUAGE", "en"); + : Configuration.DefaultContentLanguage; public static bool GetDefaultRecommendationsVisibility(this HttpContext context) => context.Request.Cookies.TryGetValue("recommendations", out string recommendations) @@ -480,4 +481,22 @@ public static SearchParams GetSearchParams(this HttpRequest request) return searchParams; } -} + + public static bool ShouldShowAlert(HttpRequest request) + { + if (Configuration.AlertHash == null) return false; + + if (request.Cookies.TryGetValue("dismissedAlert", out string? cookieVal)) + return cookieVal != Configuration.AlertHash; + + return true; + } + + public static string Md5Sum(string input) + { + using MD5 md5 = MD5.Create(); + byte[] inputBytes = Encoding.ASCII.GetBytes(input); + byte[] hashBytes = md5.ComputeHash(inputBytes); + return Convert.ToHexString(hashBytes); + } +} \ No newline at end of file diff --git a/LightTube/Views/Account/Register.cshtml b/LightTube/Views/Account/Register.cshtml index ad792048..003e8d4c 100644 --- a/LightTube/Views/Account/Register.cshtml +++ b/LightTube/Views/Account/Register.cshtml @@ -5,7 +5,7 @@ Model.HtmlTitle = "Create an account"; } -@if (Configuration.GetVariable("LIGHTTUBE_DISABLE_REGISTRATION", "false") != "false") +@if (!Configuration.RegistrationEnabled) {

This instance doesn't allow account registrations

diff --git a/LightTube/Views/Home/Error.cshtml b/LightTube/Views/Home/Error.cshtml index e434561b..b082f84e 100644 --- a/LightTube/Views/Home/Error.cshtml +++ b/LightTube/Views/Home/Error.cshtml @@ -20,7 +20,7 @@ } - + Error - LightTube @@ -28,6 +28,10 @@ + @if (Configuration.CustomCssPath != null) + { + + }

Whoops!

diff --git a/LightTube/Views/Home/Index.cshtml b/LightTube/Views/Home/Index.cshtml index 50ffc169..17f186a4 100644 --- a/LightTube/Views/Home/Index.cshtml +++ b/LightTube/Views/Home/Index.cshtml @@ -1,32 +1,30 @@ @using Humanizer
-

@Configuration.GetVariable("LIGHTTUBE_MOTD", "Search something to get started!")

+

@Configuration.RandomMessage()

@if (Model.Videos is not null) { -
- @foreach (FeedVideo video in Model.Videos) { -
- - @video.Title - -
- +
+ + @video.Title + +
+ @video.Title - -
- + + -
+ +
+
@video.ViewCount.ToString("N0") views • @video.PublishedDate.Humanize(DateTimeOffset.UtcNow) -
-
+
+
}
} diff --git a/LightTube/Views/Shared/Player.cshtml b/LightTube/Views/Shared/Player.cshtml index 09cddbe1..b6933405 100644 --- a/LightTube/Views/Shared/Player.cshtml +++ b/LightTube/Views/Shared/Player.cshtml @@ -77,7 +77,7 @@ else if ((Model.UseHls || Model.UseDash) && !Model.Player.Formats.Any()) {
+ @if (Utils.ShouldShowAlert(Context.Request)) + { +
+
+ @Configuration.Alert +
+ + + + + +
+ } @RenderBody()
@foreach (IHtmlContent item in Model.EndTags) diff --git a/LightTube/Views/Shared/_ModalLayout.cshtml b/LightTube/Views/Shared/_ModalLayout.cshtml index 4ecce37a..92b80f61 100644 --- a/LightTube/Views/Shared/_ModalLayout.cshtml +++ b/LightTube/Views/Shared/_ModalLayout.cshtml @@ -11,7 +11,7 @@ - @if (Configuration.GetVariable("LIGHTTUBE_CUSTOM_CSS_PATH") != null) + @if (Configuration.CustomCssPath != null) { } diff --git a/LightTube/Views/Shared/_SettingsLayout.cshtml b/LightTube/Views/Shared/_SettingsLayout.cshtml index 60962921..f338c93a 100644 --- a/LightTube/Views/Shared/_SettingsLayout.cshtml +++ b/LightTube/Views/Shared/_SettingsLayout.cshtml @@ -25,7 +25,7 @@ - @if (Configuration.GetVariable("LIGHTTUBE_CUSTOM_CSS_PATH") != null) + @if (Configuration.CustomCssPath != null) { } diff --git a/LightTube/wwwroot/css/lighttube.css b/LightTube/wwwroot/css/lighttube.css index 918b2837..ee65135a 100644 --- a/LightTube/wwwroot/css/lighttube.css +++ b/LightTube/wwwroot/css/lighttube.css @@ -1553,4 +1553,23 @@ code { .input-file::file-selector-button:hover { background-color: var(--btn-hover-color-white); +} + +/* LightTube Alerts */ +.layout-alert { + display: flex; + align-items: center; + padding: 12px 16px; + background-color: var(--thumbnail-background); +} + +.layout-alert_text { + flex-grow: 1; + color: var(--text-primary); + font-size: 1.2rem; +} + +.layout-alert_close { + color: var(--text-primary); + height: 20px; } \ No newline at end of file