Skip to content

Commit

Permalink
Make configs better (lighttube-org#129)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
kuylar authored Apr 9, 2024
1 parent fe676ea commit bdbc7f6
Show file tree
Hide file tree
Showing 25 changed files with 194 additions and 140 deletions.
8 changes: 3 additions & 5 deletions LightTube/ApiModels/LightTubeInstanceInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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<string, object> Config { get; set; }
}
2 changes: 1 addition & 1 deletion LightTube/Attributes/ApiDisableableAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
Expand Down
2 changes: 1 addition & 1 deletion LightTube/Attributes/OauthApiDisableableAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
Expand Down
96 changes: 62 additions & 34 deletions LightTube/Configuration.cs
Original file line number Diff line number Diff line change
@@ -1,62 +1,90 @@
using System.Text.RegularExpressions;
using InnerTube;
using Newtonsoft.Json;

namespace LightTube;

public static class Configuration
{
private static Dictionary<string, string> _variables = new();
private static Dictionary<string, string> _customThemeDefs = null;
public static Dictionary<string, string> 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<string, string> GetCustomThemeDefs()
{
if (_customThemeDefs == null)
CustomCssPath = Environment.GetEnvironmentVariable("LIGHTTUBE_CUSTOM_CSS_PATH");
if (CustomCssPath != null)
{
Dictionary<string, string> 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<string[]>(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)];
}
9 changes: 1 addition & 8 deletions LightTube/Contexts/BaseContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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}";
}
2 changes: 1 addition & 1 deletion LightTube/Contexts/PlayerContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion LightTube/Controllers/AccountController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public async Task<IActionResult> 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)
Expand Down
17 changes: 10 additions & 7 deletions LightTube/Controllers/ApiController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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<string, object>
{
["allowsApi"] = Configuration.ApiEnabled,
["allowsNewUsers"] = Configuration.RegistrationEnabled,
["allowsOauthApi"] = Configuration.OauthEnabled,
["allowsThirdPartyProxyUsage"] = Configuration.ThirdPartyProxyEnabled
}
};

private ApiResponse<T> Error<T>(string message, int code, HttpStatusCode statusCode)
Expand Down
26 changes: 16 additions & 10 deletions LightTube/Controllers/HomeController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -25,18 +26,12 @@ public HomeController(ILogger<HomeController> 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}")]
Expand All @@ -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);
}
}
14 changes: 7 additions & 7 deletions LightTube/Controllers/MediaController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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."));
Expand Down Expand Up @@ -133,7 +133,7 @@ await Response.Body.WriteAsync(Encoding.UTF8.GetBytes(
public async Task<IActionResult> 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
Expand Down Expand Up @@ -170,7 +170,7 @@ public async Task<IActionResult> HlsProxy(string videoId, string formatId, bool
public async Task<IActionResult> 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
Expand All @@ -196,7 +196,7 @@ public async Task<IActionResult> DashProxy(string videoId, string formatId, bool
[Route("hls/playlist/{path}")]
public async Task<IActionResult> 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
Expand All @@ -222,7 +222,7 @@ public async Task<IActionResult> HlsPlaylistProxy(string path, bool useProxy = t
[Route("hls/timedtext/{path}")]
public async Task<IActionResult> 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
Expand All @@ -248,7 +248,7 @@ public async Task<IActionResult> 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."));
Expand Down Expand Up @@ -359,7 +359,7 @@ public async Task<IActionResult> 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."));
Expand Down
6 changes: 3 additions & 3 deletions LightTube/Controllers/OAuth2Controller.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public async Task<IActionResult> 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"));
Expand Down Expand Up @@ -66,7 +66,7 @@ public async Task<IActionResult> 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))
Expand Down Expand Up @@ -122,7 +122,7 @@ public async Task<IActionResult> 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();
Expand Down
2 changes: 1 addition & 1 deletion LightTube/Controllers/SettingsController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public SettingsController(InnerTube.InnerTube youtube)
public async Task<IActionResult> Appearance()
{
InnerTubeLocals locals = await _youtube.GetLocalsAsync();
AppearanceSettingsContext ctx = new(HttpContext, locals, Configuration.GetCustomThemeDefs());
AppearanceSettingsContext ctx = new(HttpContext, locals, Configuration.CustomThemeDefs);
return View(ctx);
}

Expand Down
22 changes: 0 additions & 22 deletions LightTube/Controllers/TogglesController.cs

This file was deleted.

2 changes: 1 addition & 1 deletion LightTube/Database/DatabaseManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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<DatabaseUser>("users");
TokensCollection = Database.GetCollection<DatabaseLogin>("tokens");
VideoCacheCollection = Database.GetCollection<DatabaseVideo>("videoCache");
Expand Down
Loading

0 comments on commit bdbc7f6

Please sign in to comment.