lyrics support, code cleanup
This commit is contained in:
parent
193cc39ce2
commit
b9794110cd
|
@ -1,21 +0,0 @@
|
|||
# http://docs.gitlab.com/ce/ci/docker/using_docker_build.html#using-the-gitlab-container-registry
|
||||
# The docker tag is the first 6 letters of the Git commit id
|
||||
|
||||
job_build_dotnet:
|
||||
stage: build
|
||||
image: archlinux/base:latest
|
||||
variables:
|
||||
GIT_SUBMODULE_STRATEGY: recursive
|
||||
script:
|
||||
- pacman-key --init
|
||||
- pacman-key --recv-keys 3FABB87C7C9F7E5FF2B6CB7B11A7E7E4DB9351DE
|
||||
- pacman-key --lsign-key 3FABB87C7C9F7E5FF2B6CB7B11A7E7E4DB9351DE
|
||||
- bash -c "echo -e '"'[zotancc]\nServer = https://arch.prod.zotan.network/zotancc/os/$arch'"' >> /etc/pacman.conf"
|
||||
- pacman -Syu --needed dotnet-sdk-bin --noconfirm
|
||||
- curl -Lo warp-packer https://github.com/dgiagio/warp/releases/download/v0.3.0/linux-x64.warp-packer && chmod +x warp-packer
|
||||
- dotnet publish -c Release -r linux-x64
|
||||
- ./warp-packer --arch linux-x64 --input_dir bin/Release/netcoreapp3.1/linux-x64/publish --exec webmusic --output webmusic.linux.run
|
||||
- chmod +x webmusic.linux.run
|
||||
artifacts:
|
||||
paths:
|
||||
- webmusic.linux.run
|
|
@ -7,8 +7,7 @@
|
|||
<h1 class="text-danger">Error.</h1>
|
||||
<h2 class="text-danger">An error occurred while processing your request.</h2>
|
||||
|
||||
@if (Model.ShowRequestId)
|
||||
{
|
||||
@if (Model.ShowRequestId) {
|
||||
<p>
|
||||
<strong>Request ID:</strong> <code>@Model.RequestId</code>
|
||||
</p>
|
||||
|
|
|
@ -1,22 +1,15 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
|
||||
namespace webmusic.Pages
|
||||
{
|
||||
namespace webmusic.Pages {
|
||||
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
|
||||
public class ErrorModel : PageModel
|
||||
{
|
||||
public class ErrorModel : PageModel {
|
||||
public string RequestId { get; set; }
|
||||
|
||||
public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
|
||||
|
||||
public void OnGet()
|
||||
{
|
||||
public void OnGet() {
|
||||
RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,47 +1,44 @@
|
|||
@page
|
||||
@using System.Web
|
||||
@model IndexModel
|
||||
@{
|
||||
ViewData["Title"] = $"webmusic on .NET {Environment.Version}";
|
||||
var path = HttpUtility.UrlDecode(Request.QueryString.Value.TrimStart('?'));
|
||||
if (path.EndsWith(".m3u"))
|
||||
{
|
||||
Layout = null;
|
||||
Response.ContentType = "text/plain";
|
||||
}
|
||||
}
|
||||
@if (Model.path.Contains("/.."))
|
||||
{
|
||||
@if (Model.Path.Contains("/..")) {
|
||||
return;
|
||||
}
|
||||
@if (path.EndsWith(".m3u"))
|
||||
{
|
||||
@foreach (var file in Model.files)
|
||||
{
|
||||
@Html.Raw("https://" + Request.Host + "/" + Model.fullpath + "/" + file.Replace("?", "%3F") +"\n")
|
||||
}
|
||||
@if (Model.Path.EndsWith(".lrc")) {
|
||||
<h3>@Model.Path</h3>
|
||||
<p>@Html.Raw((await System.IO.File.ReadAllTextAsync("music" + Model.Path)).Replace("\n", "<br/>"))</p>
|
||||
}
|
||||
else
|
||||
{
|
||||
<h2>@Model.displaypath <span id="state"></span> <span id="flags"></span></h2>
|
||||
else {
|
||||
<h2>
|
||||
@Model.Displaypath <span id="state"></span> <span id="flags"></span>
|
||||
</h2>
|
||||
<a class="action-muted">[..]</a>
|
||||
<a href="?@Model.path_oneup" class="entry-muted cfont"> Go back</a><br/>
|
||||
<a href="?@Model.PathOneup" class="entry-muted cfont"> Go back</a>
|
||||
<br/>
|
||||
<a class="action-muted">[--]</a>
|
||||
<a href="/playlist/@(Request.QueryString).m3u" class="entry-muted cfont"> Download playlist</a><br/><br/>
|
||||
@foreach (var dir in Model.dirs)
|
||||
{
|
||||
<a href="/playlist/@(Request.QueryString).m3u" class="entry-muted cfont"> Download playlist</a>
|
||||
<br/>
|
||||
<br/>
|
||||
@foreach (var dir in Model.Dirs) {
|
||||
<a class="action" href="#">[--]</a>
|
||||
<a href="?@Model.path/@dir"> @dir</a>
|
||||
<a href="?@Model.Path/@dir"> @dir</a>
|
||||
<br/>
|
||||
}
|
||||
@foreach (var file in Model.files)
|
||||
{
|
||||
var jspath = Model.Encode(Model.fullpath);
|
||||
var jsfile = jspath + "/" + Model.Encode(file);
|
||||
@foreach (var file in Model.Files) {
|
||||
var jspath = IndexModel.Encode(Model.Fullpath);
|
||||
var jsfile = jspath + "/" + IndexModel.Encode(file);
|
||||
var basename = System.IO.Path.GetFileNameWithoutExtension(file);
|
||||
var lrcfile = basename + ".lrc";
|
||||
var lrcpath = System.IO.Path.Combine(Model.Fullpath, lrcfile);
|
||||
|
||||
<script>queue.push('@Html.Raw(jsfile)')</script>
|
||||
<a class="action" href="@Html.Raw(Model.Encode(Model.fullpath+"/"+file))" download>[DL]</a>
|
||||
<a class="action" href="@Html.Raw(IndexModel.Encode(Model.Fullpath + "/" + file))" download>[DL]</a>
|
||||
<a href="#" onclick="playSong('@Html.Raw(jsfile)')"> @file</a>
|
||||
@if (System.IO.File.Exists(lrcpath)) {
|
||||
<a class="action" href="?@Model.Path/@lrcfile" target="_blank">[LRC]</a>
|
||||
}
|
||||
<br/>
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
using System.Collections;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
@ -6,137 +6,115 @@ using System.Text.RegularExpressions;
|
|||
using System.Web;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
|
||||
namespace webmusic.Pages {
|
||||
public class IndexModel : PageModel {
|
||||
private const string Root = "music";
|
||||
public List<string> Dirs = new();
|
||||
public string Displaypath = "";
|
||||
public List<string> Files = new();
|
||||
public string Fullpath = "";
|
||||
public string Path = "";
|
||||
public string PathOneup = "";
|
||||
|
||||
namespace webmusic.Pages
|
||||
{
|
||||
public class IndexModel : PageModel
|
||||
{
|
||||
public static string root = "music";
|
||||
public string path = "";
|
||||
public string displaypath = "";
|
||||
public string path_oneup = "";
|
||||
public string fullpath = "";
|
||||
public List<string> dirs = new List<string>();
|
||||
public List<string> files = new List<string>();
|
||||
public void OnGet()
|
||||
{
|
||||
public void OnGet() {
|
||||
if (Request.QueryString.HasValue)
|
||||
path = HttpUtility.UrlDecode(Request.QueryString.Value.Remove(0,1)
|
||||
.Replace("+", "%2B"));
|
||||
if (path.EndsWith(".m3u"))
|
||||
path = path.Substring(0, path.Length - 4);
|
||||
if (path.Contains("/.."))
|
||||
{
|
||||
if (Request.QueryString.Value != null)
|
||||
Path = HttpUtility.UrlDecode(Request.QueryString.Value.TrimStart('?').Replace("+", "%2B"));
|
||||
if (Path.Contains("/..")) {
|
||||
Response.Redirect("/Error");
|
||||
return;
|
||||
}
|
||||
path_oneup = Regex.Match(path, @".*(?=\/)").Value;
|
||||
fullpath = root + path;
|
||||
displaypath = string.IsNullOrWhiteSpace(path) ? "/" : path;
|
||||
dirs = Directory.GetDirectories(fullpath).Select(Path.GetFileName).ToList();
|
||||
dirs.RemoveAll(p => p.StartsWith("."));
|
||||
dirs.Sort();
|
||||
files = Directory.GetFiles(fullpath).Select(Path.GetFileName).ToList();
|
||||
files.RemoveAll(p => p.EndsWith(".m3u"));
|
||||
files.RemoveAll(p => p.StartsWith("."));
|
||||
files.Sort(new AlphanumComparatorFast());
|
||||
|
||||
if (Path.EndsWith(".lrc"))
|
||||
return;
|
||||
|
||||
PathOneup = Regex.Match(Path, @".*(?=\/)").Value;
|
||||
Fullpath = Root + Path;
|
||||
Displaypath = string.IsNullOrWhiteSpace(Path) ? "/" : Path;
|
||||
Dirs = Directory.GetDirectories(Fullpath).Select(System.IO.Path.GetFileName).ToList();
|
||||
Dirs.RemoveAll(p => p.StartsWith("."));
|
||||
Dirs.Sort();
|
||||
Files = Directory.GetFiles(Fullpath).Select(System.IO.Path.GetFileName).ToList();
|
||||
Files.RemoveAll(p => p.EndsWith(".m3u"));
|
||||
Files.RemoveAll(p => p.EndsWith(".lrc"));
|
||||
Files.RemoveAll(p => p.StartsWith("."));
|
||||
Files.Sort(new AlphanumComparatorFast());
|
||||
}
|
||||
|
||||
public string Encode(string str)
|
||||
{
|
||||
return str.Replace("\"", "%22").Replace("'", "%27")
|
||||
.Replace("?", "%3F").Replace("&", "%26")
|
||||
public static string Encode(string str) => str.Replace("\"", "%22")
|
||||
.Replace("'", "%27")
|
||||
.Replace("?", "%3F")
|
||||
.Replace("&", "%26")
|
||||
.Replace(" ", "%20");
|
||||
}
|
||||
|
||||
public class AlphanumComparatorFast : IComparer<string>
|
||||
{
|
||||
public int Compare(string x, string y)
|
||||
{
|
||||
string s1 = x;
|
||||
private class AlphanumComparatorFast : IComparer<string> {
|
||||
public int Compare(string x, string y) {
|
||||
var s1 = x;
|
||||
if (s1 == null)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(y is string s2))
|
||||
{
|
||||
if (!(y is { } s2))
|
||||
return 0;
|
||||
}
|
||||
|
||||
int len1 = s1.Length;
|
||||
int len2 = s2.Length;
|
||||
int marker1 = 0;
|
||||
int marker2 = 0;
|
||||
var len1 = s1.Length;
|
||||
var len2 = s2.Length;
|
||||
var marker1 = 0;
|
||||
var marker2 = 0;
|
||||
|
||||
// Walk through two the strings with two markers.
|
||||
while (marker1 < len1 && marker2 < len2)
|
||||
{
|
||||
char ch1 = s1[marker1];
|
||||
char ch2 = s2[marker2];
|
||||
while (marker1 < len1 && marker2 < len2) {
|
||||
var ch1 = s1[marker1];
|
||||
var ch2 = s2[marker2];
|
||||
|
||||
// Some buffers we can build up characters in for each chunk.
|
||||
char[] space1 = new char[len1];
|
||||
int loc1 = 0;
|
||||
char[] space2 = new char[len2];
|
||||
int loc2 = 0;
|
||||
var space1 = new char[len1];
|
||||
var loc1 = 0;
|
||||
var space2 = new char[len2];
|
||||
var loc2 = 0;
|
||||
|
||||
// Walk through all following characters that are digits or
|
||||
// characters in BOTH strings starting at the appropriate marker.
|
||||
// Collect char arrays.
|
||||
do
|
||||
{
|
||||
do {
|
||||
space1[loc1++] = ch1;
|
||||
marker1++;
|
||||
|
||||
if (marker1 < len1)
|
||||
{
|
||||
ch1 = s1[marker1];
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
} while (char.IsDigit(ch1) == char.IsDigit(space1[0]));
|
||||
|
||||
do
|
||||
{
|
||||
do {
|
||||
space2[loc2++] = ch2;
|
||||
marker2++;
|
||||
|
||||
if (marker2 < len2)
|
||||
{
|
||||
ch2 = s2[marker2];
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
} while (char.IsDigit(ch2) == char.IsDigit(space2[0]));
|
||||
|
||||
// If we have collected numbers, compare them numerically.
|
||||
// Otherwise, if we have strings, compare them alphabetically.
|
||||
string str1 = new string(space1);
|
||||
string str2 = new string(space2);
|
||||
var str1 = new string(space1);
|
||||
var str2 = new string(space2);
|
||||
|
||||
int result;
|
||||
|
||||
if (char.IsDigit(space1[0]) && char.IsDigit(space2[0]))
|
||||
{
|
||||
int thisNumericChunk = int.Parse(str1);
|
||||
int thatNumericChunk = int.Parse(str2);
|
||||
if (char.IsDigit(space1[0]) && char.IsDigit(space2[0])) {
|
||||
var thisNumericChunk = int.Parse(str1);
|
||||
var thatNumericChunk = int.Parse(str2);
|
||||
result = thisNumericChunk.CompareTo(thatNumericChunk);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = str1.CompareTo(str2);
|
||||
else {
|
||||
result = string.Compare(str1, str2, StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
if (result != 0)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return len1 - len2;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
</head>
|
||||
<body>
|
||||
<div id="container">
|
||||
@RenderBody()
|
||||
@RenderBody()
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -1,19 +1,15 @@
|
|||
@page
|
||||
@using System.Web
|
||||
@model IndexModel
|
||||
@{
|
||||
Layout = null;
|
||||
Response.ContentType = "text/plain";
|
||||
}
|
||||
@if (Model.path.Contains(".."))
|
||||
{
|
||||
@if (Model.Path.Contains("..")) {
|
||||
return;
|
||||
}
|
||||
@foreach (var dir in Model.dirs)
|
||||
{
|
||||
@Html.Raw(dir+"\n")
|
||||
@foreach (var dir in Model.Dirs) {
|
||||
@Html.Raw(dir + "\n")
|
||||
}
|
||||
@foreach (var file in Model.files)
|
||||
{
|
||||
@Html.Raw(file+"\n")
|
||||
@foreach (var file in Model.Files) {
|
||||
@Html.Raw(file + "\n")
|
||||
}
|
|
@ -6,11 +6,9 @@
|
|||
Layout = null;
|
||||
Response.ContentType = "text/plain";
|
||||
}
|
||||
@if (Model.path.Contains(".."))
|
||||
{
|
||||
@if (Model.Path.Contains("..")) {
|
||||
return;
|
||||
}
|
||||
@foreach (var file in Model.files)
|
||||
{
|
||||
@Html.Raw("https://" + Request.Host + "/" + Model.fullpath + "/" + file.Replace("?", "%3F") +"\n")
|
||||
@foreach (var file in Model.Files) {
|
||||
@Html.Raw("https://" + Request.Host + "/" + Model.Fullpath + "/" + file.Replace("?", "%3F") + "\n")
|
||||
}
|
22
Program.cs
22
Program.cs
|
@ -1,25 +1,13 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore;
|
||||
using Microsoft.AspNetCore;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace webmusic
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
namespace webmusic {
|
||||
public class Program {
|
||||
public static void Main(string[] args) {
|
||||
CreateWebHostBuilder(args).Build().Run();
|
||||
}
|
||||
|
||||
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
|
||||
WebHost.CreateDefaultBuilder(args)
|
||||
.UseWebRoot(".")
|
||||
.UseStartup<Startup>();
|
||||
WebHost.CreateDefaultBuilder(args).UseWebRoot(".").UseStartup<Startup>();
|
||||
}
|
||||
}
|
41
Startup.cs
41
Startup.cs
|
@ -1,65 +1,42 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.HttpsPolicy;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.StaticFiles;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
|
||||
namespace webmusic
|
||||
{
|
||||
public class Startup
|
||||
{
|
||||
public Startup(IConfiguration configuration)
|
||||
{
|
||||
Configuration = configuration;
|
||||
}
|
||||
|
||||
public IConfiguration Configuration { get; }
|
||||
|
||||
namespace webmusic {
|
||||
public class Startup {
|
||||
// This method gets called by the runtime. Use this method to add services to the container.
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
services.Configure<CookiePolicyOptions>(options =>
|
||||
{
|
||||
public static void ConfigureServices(IServiceCollection services) {
|
||||
services.Configure<CookiePolicyOptions>(options => {
|
||||
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
|
||||
options.CheckConsentNeeded = context => true;
|
||||
options.MinimumSameSitePolicy = SameSiteMode.None;
|
||||
});
|
||||
|
||||
|
||||
services.Configure<MvcOptions>(options => { options.EnableEndpointRouting = false; });
|
||||
|
||||
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Latest);
|
||||
}
|
||||
|
||||
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
||||
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
|
||||
{
|
||||
public static void Configure(IApplicationBuilder app, IWebHostEnvironment env) {
|
||||
var provider = new FileExtensionContentTypeProvider();
|
||||
provider.Mappings[".flac"] = "audio/flac";
|
||||
provider.Mappings[".m3u"] = "audio/m3u";
|
||||
provider.Mappings[".opus"] = "audio/opus";
|
||||
if (env.IsDevelopment())
|
||||
{
|
||||
if (env.IsDevelopment()) {
|
||||
app.UseDeveloperExceptionPage();
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
app.UseExceptionHandler("/Error");
|
||||
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
|
||||
app.UseHsts();
|
||||
}
|
||||
|
||||
app.UseStaticFiles(new StaticFileOptions()
|
||||
{
|
||||
ContentTypeProvider = provider
|
||||
});
|
||||
app.UseStaticFiles(new StaticFileOptions {ContentTypeProvider = provider});
|
||||
app.UseCookiePolicy();
|
||||
|
||||
app.UseMvc();
|
||||
|
|
Loading…
Reference in a new issue