[optimize] code optimize

This commit is contained in:
acite
2025-09-09 12:11:30 +08:00
parent 99a5e42d99
commit 3e03b13d11
11 changed files with 166 additions and 43 deletions

View File

@@ -10,24 +10,21 @@
</component>
<component name="ChangeListManager">
<list default="true" id="bf317275-3039-49bb-a475-725a800a0cce" name="Changes" comment="">
<change afterPath="$PROJECT_DIR$/Abyss/Components/Controllers/Task/TaskController.cs" afterDir="false" />
<change afterPath="$PROJECT_DIR$/Abyss/Components/Services/TaskService.cs" afterDir="false" />
<change afterPath="$PROJECT_DIR$/Abyss/Components/Tools/TemporaryDB.cs" afterDir="false" />
<change afterPath="$PROJECT_DIR$/Abyss/Model/Chip.cs" afterDir="false" />
<change afterPath="$PROJECT_DIR$/Abyss/Model/Comment.cs" afterDir="false" />
<change afterPath="$PROJECT_DIR$/Abyss/Model/Task.cs" afterDir="false" />
<change afterPath="$PROJECT_DIR$/Abyss/Model/TaskCreation.cs" afterDir="false" />
<change afterPath="$PROJECT_DIR$/Abyss/Model/Video.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.gitignore" beforeDir="false" afterPath="$PROJECT_DIR$/.gitignore" afterDir="false" />
<change afterPath="$PROJECT_DIR$/Abyss/Toolkits/image-creator.py" afterDir="false" />
<change afterPath="$PROJECT_DIR$/Abyss/Toolkits/image-sum.py" afterDir="false" />
<change afterPath="$PROJECT_DIR$/Abyss/Toolkits/update-tags.py" afterDir="false" />
<change afterPath="$PROJECT_DIR$/Abyss/Toolkits/update-video.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/.idea.Abyss/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/.idea.Abyss/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Abyss.sln.DotSettings.user" beforeDir="false" afterPath="$PROJECT_DIR$/Abyss.sln.DotSettings.user" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Abyss/Components/Controllers/Media/ImageController.cs" beforeDir="false" afterPath="$PROJECT_DIR$/Abyss/Components/Controllers/Media/ImageController.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Abyss/Components/Controllers/Media/VideoController.cs" beforeDir="false" afterPath="$PROJECT_DIR$/Abyss/Components/Controllers/Media/VideoController.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Abyss/Components/Services/ConfigureService.cs" beforeDir="false" afterPath="$PROJECT_DIR$/Abyss/Components/Services/ConfigureService.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Abyss/Components/Services/ResourceService.cs" beforeDir="false" afterPath="$PROJECT_DIR$/Abyss/Components/Services/ResourceService.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Abyss/Components/Services/UserService.cs" beforeDir="false" afterPath="$PROJECT_DIR$/Abyss/Components/Services/UserService.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Abyss/Components/Static/Helpers.cs" beforeDir="false" afterPath="$PROJECT_DIR$/Abyss/Components/Static/Helpers.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Abyss/Program.cs" beforeDir="false" afterPath="$PROJECT_DIR$/Abyss/Program.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Abyss/Components/Tools/NaturalStringComparer.cs" beforeDir="false" afterPath="$PROJECT_DIR$/Abyss/Components/Tools/NaturalStringComparer.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Abyss/Model/Bookmark.cs" beforeDir="false" afterPath="$PROJECT_DIR$/Abyss/Model/Bookmark.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Abyss/Model/Comic.cs" beforeDir="false" afterPath="$PROJECT_DIR$/Abyss/Model/Comic.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Abyss/Properties/launchSettings.json" beforeDir="false" afterPath="$PROJECT_DIR$/Abyss/Properties/launchSettings.json" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Abyss/appsettings.Development.json" beforeDir="false" />
</list>
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
@@ -43,6 +40,7 @@
<component name="HighlightingSettingsPerFile">
<setting file="file://$APPLICATION_CONFIG_DIR$/resharper-host/DecompilerCache/decompiler/011a191356a243438f987de3ec3d6c6230800/04/8419ff35/ServiceProvider.cs" root0="FORCE_HIGHLIGHTING" />
<setting file="file://$APPLICATION_CONFIG_DIR$/resharper-host/DecompilerCache/decompiler/457530be4752476295767457c3639889d1a000/4c/4b962087/Monitor.cs" root0="FORCE_HIGHLIGHTING" />
<setting file="file://$APPLICATION_CONFIG_DIR$/resharper-host/DecompilerCache/decompiler/457530be4752476295767457c3639889d1a000/d0/3b166e9e/String.cs" root0="FORCE_HIGHLIGHTING" />
<setting file="file://$APPLICATION_CONFIG_DIR$/resharper-host/DecompilerCache/decompiler/5df2accb46d040ccbbbe8331bf4d24b61daa00/df/93debd37/ControllerBase.cs" root0="FORCE_HIGHLIGHTING" />
<setting file="file://$APPLICATION_CONFIG_DIR$/resharper-host/DecompilerCache/decompiler/7598e47d5cdf4107ba88f8220720fdc89000/a6/79d67871/xxHash128.cs" root0="FORCE_HIGHLIGHTING" />
<setting file="file://$APPLICATION_CONFIG_DIR$/resharper-host/DecompilerCache/decompiler/f09ccaeb94c34c2299acd3efee0facee1a400/81/137b58b4/Key.cs" root0="FORCE_HIGHLIGHTING" />
@@ -54,9 +52,10 @@
<setting file="file://$PROJECT_DIR$/Abyss/Components/Services/TaskService.cs" root0="FORCE_HIGHLIGHTING" />
<setting file="file://$PROJECT_DIR$/Abyss/Components/Services/UserService.cs" root0="FORCE_HIGHLIGHTING" />
<setting file="file://$PROJECT_DIR$/Abyss/Components/Static/Helpers.cs" root0="FORCE_HIGHLIGHTING" />
<setting file="file://$PROJECT_DIR$/Abyss/Components/Tools/TemporaryDB.cs" root0="FORCE_HIGHLIGHTING" />
<setting file="file://$PROJECT_DIR$/Abyss/Model/Bookmark.cs" root0="FORCE_HIGHLIGHTING" />
<setting file="file://$PROJECT_DIR$/Abyss/Model/ChallengeResponse.cs" root0="FORCE_HIGHLIGHTING" />
<setting file="file://$PROJECT_DIR$/Abyss/Model/Chip.cs" root0="FORCE_HIGHLIGHTING" />
<setting file="file://$PROJECT_DIR$/Abyss/Model/Comic.cs" root0="FORCE_HIGHLIGHTING" />
<setting file="file://$PROJECT_DIR$/Abyss/Model/Comment.cs" root0="FORCE_HIGHLIGHTING" />
<setting file="file://$PROJECT_DIR$/Abyss/Model/ResourceAttribute.cs" root0="FORCE_HIGHLIGHTING" />
<setting file="file://$PROJECT_DIR$/Abyss/Model/Task.cs" root0="FORCE_HIGHLIGHTING" />
@@ -65,6 +64,7 @@
<setting file="file://$PROJECT_DIR$/Abyss/Model/UserCreating.cs" root0="FORCE_HIGHLIGHTING" />
<setting file="file://$PROJECT_DIR$/Abyss/Model/Video.cs" root0="FORCE_HIGHLIGHTING" />
<setting file="file://$PROJECT_DIR$/AbyssCli/Program.cs" root0="FORCE_HIGHLIGHTING" />
<setting file="file:///storage/Images/31/summary.json" root0="FORCE_HIGHLIGHTING" />
<setting file="file:///usr/lib/dotnet/sdk/9.0.109/Sdks/Microsoft.NET.Sdk/targets/Microsoft.NET.Sdk.targets" root0="FORCE_HIGHLIGHTING" />
</component>
<component name="MetaFilesCheckinStateConfiguration" checkMetaFiles="true" />
@@ -93,17 +93,17 @@
"RunOnceActivity.git.unshallow": "true",
"XThreadsFramesViewSplitterKey": "0.30266345",
"git-widget-placeholder": "dev-task",
"last_opened_file_path": "/home/acite/embd/WebProjects/Abyss/.gitignore",
"last_opened_file_path": "/storage/Images/31/summary.json",
"node.js.detected.package.eslint": "true",
"node.js.detected.package.tslint": "true",
"node.js.selected.package.eslint": "(autodetect)",
"node.js.selected.package.tslint": "(autodetect)",
"nodejs_package_manager_path": "npm",
"settings.editor.selected.configurable": "preferences.pluginManager",
"settings.editor.selected.configurable": "com.jetbrains.python.configuration.PyActiveSdkModuleConfigurable",
"vue.rearranger.settings.migration": "true"
}
}]]></component>
<component name="RunManager" selected=".NET Launch Settings Profile.Abyss: https">
<component name="RunManager" selected="Publish to folder.Publish Abyss to folder">
<configuration name="Publish Abyss to folder x86" type="DotNetFolderPublish" factoryName="Publish to folder">
<riderPublish configuration="Release" platform="Any CPU" produce_single_file="true" ready_to_run="true" self_contained="true" target_folder="/opt/security/https/server" target_framework="net9.0" uuid_high="3690631506471504162" uuid_low="-4858628519588143325">
<runtimes>
@@ -198,7 +198,19 @@
<workItem from="1756145197559" duration="780000" />
<workItem from="1756205686118" duration="5398000" />
<workItem from="1756277940361" duration="1097000" />
<workItem from="1756293105406" duration="17059000" />
<workItem from="1756293105406" duration="18336000" />
<workItem from="1756364194123" duration="748000" />
<workItem from="1756553959939" duration="2071000" />
<workItem from="1756611257955" duration="11070000" />
<workItem from="1756693065091" duration="645000" />
<workItem from="1756879449291" duration="630000" />
<workItem from="1756905732385" duration="955000" />
<workItem from="1756953389550" duration="29000" />
<workItem from="1756995048032" duration="3919000" />
<workItem from="1757064153985" duration="1107000" />
<workItem from="1757076719875" duration="601000" />
<workItem from="1757219779961" duration="112000" />
<workItem from="1757386288260" duration="3634000" />
</task>
<servers />
</component>
@@ -218,7 +230,7 @@
<entry key="branch">
<value>
<list>
<option value="main" />
<option value="dev-task" />
</list>
</value>
</entry>
@@ -248,19 +260,6 @@
<properties exception="System.Threading.ThreadAbortException" breakIfHandledByOtherCode="false" displayValue="System.Threading.ThreadAbortException" />
<option name="timeStamp" value="3" />
</breakpoint>
<line-breakpoint enabled="true" type="DotNet Breakpoints">
<url>file://$PROJECT_DIR$/Abyss/Components/Services/TaskService.cs</url>
<line>60</line>
<properties documentPath="$PROJECT_DIR$/Abyss/Components/Services/TaskService.cs" containingFunctionPresentation="Method 'CreateVideoTask'">
<startOffsets>
<option value="2099" />
</startOffsets>
<endOffsets>
<option value="2163" />
</endOffsets>
</properties>
<option name="timeStamp" value="13" />
</line-breakpoint>
</breakpoints>
</breakpoint-manager>
</component>

View File

@@ -3,4 +3,5 @@
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AKey_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2025_002E2_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Ff09ccaeb94c34c2299acd3efee0facee1a400_003F81_003F137b58b4_003FKey_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AMonitor_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2025_002E2_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F457530be4752476295767457c3639889d1a000_003F4c_003F4b962087_003FMonitor_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AServiceProvider_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2025_002E2_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F011a191356a243438f987de3ec3d6c6230800_003F04_003F8419ff35_003FServiceProvider_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AString_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2025_002E2_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F457530be4752476295767457c3639889d1a000_003Fd0_003F3b166e9e_003FString_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AxxHash128_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2025_002E2_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F7598e47d5cdf4107ba88f8220720fdc89000_003Fa6_003F79d67871_003FxxHash128_002Ecs/@EntryIndexedValue">ForceIncluded</s:String></wpf:ResourceDictionary>

View File

@@ -1,6 +1,9 @@
using Abyss.Components.Services;
using Abyss.Components.Static;
using Abyss.Components.Tools;
using Abyss.Model;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace Abyss.Components.Controllers.Media;
@@ -28,7 +31,7 @@ public class ImageController(ILogger<ImageController> logger, ResourceService rs
if(r == null)
return StatusCode(401, new { message = "Unauthorized" });
return Ok(r);
return Ok(r.NaturalSort(x => x));
}
[HttpGet("{id}")]
@@ -43,6 +46,27 @@ public class ImageController(ILogger<ImageController> logger, ResourceService rs
return Ok(await System.IO.File.ReadAllTextAsync(d));
}
[HttpPost("{id}/bookmark")]
public async Task<IActionResult> Bookmark(string id, string token, [FromBody] Bookmark bookmark)
{
var d = Helpers.SafePathCombine(ImageFolder, [id, "summary.json"]);
if (d == null) return StatusCode(403, new { message = "403 Denied" });
var r = await rs.Update(d, token, Ip);
if (!r) return StatusCode(403, new { message = "403 Denied" });
Comic c = JsonConvert.DeserializeObject<Comic>(await System.IO.File.ReadAllTextAsync(d))!;
var bookmarkPage = Helpers.SafePathCombine(ImageFolder, [id, bookmark.Page]);
if(!System.IO.File.Exists(bookmarkPage))
return BadRequest();
c.Bookmarks.Add(bookmark);
var o = JsonConvert.SerializeObject(c);
await System.IO.File.WriteAllTextAsync(d, o);
return Ok();
}
[HttpGet("{id}/{file}")]
public async Task<IActionResult> Get(string id, string file, string token)
{

View File

@@ -1,7 +1,10 @@
using System.Diagnostics;
using Abyss.Components.Services;
using Abyss.Components.Static;
using Abyss.Components.Tools;
using Abyss.Model;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
namespace Abyss.Components.Controllers.Media;
@@ -38,10 +41,24 @@ public class VideoController(ILogger<VideoController> logger, ResourceService rs
var d = Helpers.SafePathCombine(VideoFolder, klass);
if (d == null) return StatusCode(403, new { message = "403 Denied" });
var r = await rs.Query(d, token, Ip);
if (r == null) return StatusCode(401, new { message = "Unauthorized" });
return Ok(r);
var rv = r.Select(x =>
{
return Helpers.SafePathCombine(VideoFolder, [klass, x, "summary.json"]);
}).ToArray();
for (int i = 0; i < rv.Length; i++)
{
if(rv[i] == null) continue;
rv[i] = await System.IO.File.ReadAllTextAsync(rv[i] ?? "");
}
var sv = rv.Where(x => x!=null).Select(x => x ?? "")
.Select(x => JsonConvert.DeserializeObject<Video>(x)).ToArray();
return Ok(sv.Zip(r, (x, y) => (x, y)).NaturalSort(x => x.x.name).Select(x => x.y).ToArray());
}
[HttpGet("{klass}/{id}")]

View File

@@ -3,6 +3,7 @@ namespace Abyss.Components.Services;
public class ConfigureService
{
public string MediaRoot { get; set; } = Environment.GetEnvironmentVariable("MEDIA_ROOT") ?? "/opt";
public string DebugMode { get; set; } = Environment.GetEnvironmentVariable("DEBUG_MODE") ?? "Production";
public string Version { get; } = "Alpha v0.1";
public string UserDatabase { get; set; } = "user.db";
public string RaDatabase { get; set; } = "ra.db";

View File

@@ -27,7 +27,7 @@ public class ResourceService
private readonly SQLiteAsyncConnection _database;
private static readonly Regex PermissionRegex =
new Regex(@"^([r-][w-]),([r-][w-]),([r-][w-])$", RegexOptions.Compiled);
new(@"^([r-][w-]),([r-][w-]),([r-][w-])$", RegexOptions.Compiled);
public ResourceService(ILogger<ResourceService> logger, ConfigureService config, IMemoryCache cache,
UserService user)
@@ -47,7 +47,7 @@ public class ResourceService
}
// Create UID only for resources, without considering advanced hash security such as adding salt
private string Uid(string path)
private static string Uid(string path)
{
var b = Encoding.UTF8.GetBytes(path);
var r = XxHash128.Hash(b, 0x11451419);
@@ -169,8 +169,16 @@ public class ResourceService
return await Valid(path, token, OperationType.Read, ip);
}
public async Task<bool> Update(string path, string token, string ip)
{
return await Valid(path, token, OperationType.Write, ip);
}
public async Task<bool> Initialize(string path, string token, string username, string ip)
{
// TODO: Use a more elegant Debug mode
if (_config.DebugMode == "Debug")
goto debug;
// 1. Authorization: Verify the operation is performed by 'root'
var requester = _user.Validate(token, ip);
if (requester != "root")
@@ -178,7 +186,7 @@ public class ResourceService
_logger.LogWarning($"Permission denied: Non-root user '{requester ?? "unknown"}' attempted to initialize resources.");
return false;
}
debug:
// 2. Validation: Ensure the target path and owner are valid
if (!Directory.Exists(path))
{

View File

@@ -28,7 +28,9 @@ public class UserService
_database.CreateTableAsync<User>().Wait();
var rootUser = _database.Table<User>().Where(x => x.Name == "root").FirstOrDefaultAsync().Result;
_cache.Set("acite", $"acite@127.0.0.1", DateTimeOffset.Now.AddDays(1));
if (_config.DebugMode == "Debug")
_cache.Set("root", $"root@127.0.0.1", DateTimeOffset.Now.AddHours(1));
// Test token, can only be used locally. Will be destroyed in one hour.
if (rootUser == null)
{

View File

@@ -1,6 +1,60 @@
namespace Abyss.Components.Tools;
public class TemporaryDB
public static class NaturalSortExtensions
{
public static IOrderedEnumerable<T> NaturalSort<T>(this IEnumerable<T> source, Func<T, string> keySelector)
{
return source.OrderBy(keySelector, new NaturalStringComparer());
}
}
public class NaturalStringComparer : IComparer<string>
{
public int Compare(string? a, string? b)
{
if (a == null && b == null) return 0;
if (a == null) return -1;
if (b == null) return 1;
int aIndex = 0;
int bIndex = 0;
while (aIndex < a.Length && bIndex < b.Length)
{
if (char.IsDigit(a[aIndex]) && char.IsDigit(b[bIndex]))
{
long aNum = 0;
long bNum = 0;
while (aIndex < a.Length && char.IsDigit(a[aIndex]))
{
aNum = aNum * 10 + (a[aIndex] - '0');
aIndex++;
}
while (bIndex < b.Length && char.IsDigit(b[bIndex]))
{
bNum = bNum * 10 + (b[bIndex] - '0');
bIndex++;
}
if (aNum != bNum)
{
return aNum.CompareTo(bNum);
}
}
else
{
int charCompare = a[aIndex].CompareTo(b[bIndex]);
if (charCompare != 0)
{
return charCompare;
}
aIndex++;
bIndex++;
}
}
return a.Length.CompareTo(b.Length);
}
}

View File

@@ -1,6 +1,11 @@
using Newtonsoft.Json;
namespace Abyss.Model;
public class Bookmark
{
[JsonProperty("page")]
public string Page { get; set; } = "";
[JsonProperty("name")]
public string Name { get; set; } = "";
}

View File

@@ -1,6 +1,17 @@
using Newtonsoft.Json;
namespace Abyss.Model;
public class Comic
{
[JsonProperty("comic_name")]
public string ComicName { get; set; } = "";
[JsonProperty("page_count")]
public int PageCount { get; set; }
[JsonProperty("bookmarks")]
public List<Bookmark> Bookmarks { get; set; } = new();
[JsonProperty("author")]
public string Author { get; set; } = "";
[JsonProperty("list")]
public List<string> List { get; set; } = new();
}

View File

@@ -18,7 +18,8 @@
"applicationUrl": "https://localhost:7013;http://localhost:5198",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"MEDIA_ROOT" : "/storage"
"MEDIA_ROOT" : "/storage",
"DEBUG_MODE" : "Debug"
}
}
}