[feat] Sort query results
This commit is contained in:
94
.idea/.idea.Abyss/.idea/workspace.xml
generated
94
.idea/.idea.Abyss/.idea/workspace.xml
generated
@@ -10,10 +10,10 @@
|
||||
</component>
|
||||
<component name="ChangeListManager">
|
||||
<list default="true" id="bf317275-3039-49bb-a475-725a800a0cce" name="Changes" comment="">
|
||||
<change beforePath="$PROJECT_DIR$/.gitignore" beforeDir="false" afterPath="$PROJECT_DIR$/.gitignore" 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/Components/Controllers/Media/VideoController.cs" beforeDir="false" afterPath="$PROJECT_DIR$/Abyss/Components/Controllers/Media/VideoController.cs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Abyss/appsettings.json" beforeDir="false" afterPath="$PROJECT_DIR$/Abyss/appsettings.json" 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" />
|
||||
</list>
|
||||
<option name="SHOW_DIALOG" value="false" />
|
||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||
@@ -32,10 +32,14 @@
|
||||
<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" />
|
||||
<setting file="file://$PROJECT_DIR$/Abyss/Components/Controllers/AbyssController.cs" root0="FORCE_HIGHLIGHTING" />
|
||||
<setting file="mock:///home/acite/embd/WebProjects/Abyss/Abyss/Components/Controllers/Media/VideoController.cs" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///home/acite/embd/WebProjects/Abyss/Abyss/Components/Controllers/Media/VideoController.cs" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="file://$PROJECT_DIR$/Abyss/Components/Controllers/Security/UserController.cs" root0="FORCE_HIGHLIGHTING" />
|
||||
<setting file="file://$PROJECT_DIR$/Abyss/Components/Services/ConfigureService.cs" root0="FORCE_HIGHLIGHTING" />
|
||||
<setting file="file://$PROJECT_DIR$/Abyss/Components/Services/ResourceService.cs" root0="FORCE_HIGHLIGHTING" />
|
||||
<setting file="file://$PROJECT_DIR$/Abyss/Components/Services/UserService.cs" root0="FORCE_HIGHLIGHTING" />
|
||||
<setting file="mock:///home/acite/embd/WebProjects/Abyss/Abyss/Components/Services/UserService.cs" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///home/acite/embd/WebProjects/Abyss/Abyss/Components/Services/UserService.cs" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="file://$PROJECT_DIR$/Abyss/Components/Static/Helpers.cs" root0="FORCE_HIGHLIGHTING" />
|
||||
<setting file="file://$PROJECT_DIR$/Abyss/Model/ChallengeResponse.cs" root0="FORCE_HIGHLIGHTING" />
|
||||
<setting file="file://$PROJECT_DIR$/Abyss/Model/ResourceAttribute.cs" root0="FORCE_HIGHLIGHTING" />
|
||||
@@ -52,32 +56,33 @@
|
||||
<option name="hideEmptyMiddlePackages" value="true" />
|
||||
<option name="showLibraryContents" value="true" />
|
||||
</component>
|
||||
<component name="PropertiesComponent"><![CDATA[{
|
||||
"keyToString": {
|
||||
".NET Launch Settings Profile.Abyss: http.executor": "Run",
|
||||
".NET Project.AbyssCli.executor": "Run",
|
||||
"ASKED_SHARE_PROJECT_CONFIGURATION_FILES": "true",
|
||||
"ModuleVcsDetector.initialDetectionPerformed": "true",
|
||||
"Publish to folder.Publish Abyss to folder x86.executor": "Run",
|
||||
"Publish to folder.Publish Abyss to folder.executor": "Run",
|
||||
"RunOnceActivity.ShowReadmeOnStart": "true",
|
||||
"RunOnceActivity.TerminalTabsStorage.copyFrom.TerminalArrangementManager.252": "true",
|
||||
"RunOnceActivity.git.unshallow": "true",
|
||||
"XThreadsFramesViewSplitterKey": "0.30266345",
|
||||
"git-widget-placeholder": "main",
|
||||
"last_opened_file_path": "/home/acite/embd/WebProjects/Abyss/.gitignore",
|
||||
"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",
|
||||
"vue.rearranger.settings.migration": "true"
|
||||
<component name="PropertiesComponent">{
|
||||
"keyToString": {
|
||||
".NET Launch Settings Profile.Abyss: http.executor": "Run",
|
||||
".NET Launch Settings Profile.Abyss: https.executor": "Run",
|
||||
".NET Project.AbyssCli.executor": "Run",
|
||||
"ASKED_SHARE_PROJECT_CONFIGURATION_FILES": "true",
|
||||
"ModuleVcsDetector.initialDetectionPerformed": "true",
|
||||
"Publish to folder.Publish Abyss to folder x86.executor": "Run",
|
||||
"Publish to folder.Publish Abyss to folder.executor": "Run",
|
||||
"RunOnceActivity.ShowReadmeOnStart": "true",
|
||||
"RunOnceActivity.TerminalTabsStorage.copyFrom.TerminalArrangementManager.252": "true",
|
||||
"RunOnceActivity.git.unshallow": "true",
|
||||
"XThreadsFramesViewSplitterKey": "0.30266345",
|
||||
"git-widget-placeholder": "main",
|
||||
"last_opened_file_path": "/opt/security/https/server",
|
||||
"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",
|
||||
"vue.rearranger.settings.migration": "true"
|
||||
}
|
||||
}]]></component>
|
||||
<component name="RunManager" selected=".NET Launch Settings Profile.Abyss: http">
|
||||
}</component>
|
||||
<component name="RunManager" selected="Publish to folder.Publish Abyss to folder x86">
|
||||
<configuration name="Publish Abyss to folder x86" type="DotNetFolderPublish" factoryName="Publish to folder">
|
||||
<riderPublish configuration="Release" platform="Any CPU" produce_single_file="true" self_contained="true" target_folder="$PROJECT_DIR$/Abyss/bin/Release/net9.0/linux-x64/publish" target_framework="net9.0" uuid_high="3690631506471504162" uuid_low="-4858628519588143325">
|
||||
<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>
|
||||
<item value="linux-x64" />
|
||||
</runtimes>
|
||||
@@ -85,7 +90,7 @@
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
<configuration name="Publish Abyss to folder" type="DotNetFolderPublish" factoryName="Publish to folder">
|
||||
<riderPublish configuration="Release" platform="Any CPU" self_contained="true" target_folder="$PROJECT_DIR$/Abyss/bin/Release/net9.0/publish" target_framework="net9.0" uuid_high="3690631506471504162" uuid_low="-4858628519588143325">
|
||||
<riderPublish configuration="Release" platform="Any CPU" produce_single_file="true" self_contained="true" target_folder="$PROJECT_DIR$/Abyss/bin/Release/net9.0/publish" target_framework="net9.0" uuid_high="3690631506471504162" uuid_low="-4858628519588143325">
|
||||
<runtimes>
|
||||
<item value="linux-arm64" />
|
||||
</runtimes>
|
||||
@@ -147,6 +152,13 @@
|
||||
<option name="Build" />
|
||||
</method>
|
||||
</configuration>
|
||||
<list>
|
||||
<item itemvalue=".NET Launch Settings Profile.Abyss: http" />
|
||||
<item itemvalue=".NET Launch Settings Profile.Abyss: https" />
|
||||
<item itemvalue=".NET Project.AbyssCli" />
|
||||
<item itemvalue="Publish to folder.Publish Abyss to folder" />
|
||||
<item itemvalue="Publish to folder.Publish Abyss to folder x86" />
|
||||
</list>
|
||||
</component>
|
||||
<component name="TaskManager">
|
||||
<task active="true" id="Default" summary="Default task">
|
||||
@@ -159,7 +171,10 @@
|
||||
<workItem from="1755878548611" duration="22675000" />
|
||||
<workItem from="1755924449835" duration="39604000" />
|
||||
<workItem from="1756025651909" duration="43000" />
|
||||
<workItem from="1756121403390" duration="4269000" />
|
||||
<workItem from="1756121403390" duration="7316000" />
|
||||
<workItem from="1756145197559" duration="780000" />
|
||||
<workItem from="1756205686118" duration="5398000" />
|
||||
<workItem from="1756277940361" duration="862000" />
|
||||
</task>
|
||||
<servers />
|
||||
</component>
|
||||
@@ -168,6 +183,29 @@
|
||||
</component>
|
||||
<component name="UnityCheckinConfiguration" checkUnsavedScenes="true" />
|
||||
<component name="UnityProjectConfiguration" hasMinimizedUI="false" />
|
||||
<component name="Vcs.Log.Tabs.Properties">
|
||||
<option name="TAB_STATES">
|
||||
<map>
|
||||
<entry key="MAIN">
|
||||
<value>
|
||||
<State>
|
||||
<option name="FILTERS">
|
||||
<map>
|
||||
<entry key="branch">
|
||||
<value>
|
||||
<list>
|
||||
<option value="main" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
</map>
|
||||
</option>
|
||||
</State>
|
||||
</value>
|
||||
</entry>
|
||||
</map>
|
||||
</option>
|
||||
</component>
|
||||
<component name="VcsManagerConfiguration">
|
||||
<option name="CLEAR_INITIAL_COMMIT_MESSAGE" value="true" />
|
||||
</component>
|
||||
|
||||
@@ -24,7 +24,7 @@ public class VideoController(ILogger<VideoController> logger, ResourceService rs
|
||||
[HttpGet]
|
||||
public async Task<IActionResult> GetClass(string token)
|
||||
{
|
||||
var r = await rs.Query(VideoFolder, token, Ip);
|
||||
var r = (await rs.Query(VideoFolder, token, Ip))?.SortLikeWindows();
|
||||
|
||||
if(r == null)
|
||||
return StatusCode(401, new { message = "Unauthorized" });
|
||||
@@ -38,6 +38,7 @@ 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);
|
||||
@@ -64,6 +65,8 @@ public class VideoController(ILogger<VideoController> logger, ResourceService rs
|
||||
var r = await rs.Get(d, token, Ip);
|
||||
if (!r) return StatusCode(403, new { message = "403 Denied" });
|
||||
|
||||
_logger.LogInformation($"Cover found for {id}");
|
||||
|
||||
return PhysicalFile(d, "image/jpeg", enableRangeProcessing: true);
|
||||
}
|
||||
|
||||
|
||||
@@ -117,7 +117,7 @@ public class UserService
|
||||
Destroy(token);
|
||||
return null;
|
||||
}
|
||||
_logger.LogInformation($"Validated {userAndIp}");
|
||||
// _logger.LogInformation($"Validated {userAndIp}");
|
||||
return userAndIp?.Split('@')[0];
|
||||
}
|
||||
_logger.LogWarning($"Validation failed {token}");
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
|
||||
using System.Globalization;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace Abyss.Components.Static;
|
||||
|
||||
public static class Helpers
|
||||
@@ -57,4 +60,121 @@ public enum PathType
|
||||
Directory,
|
||||
NotFound,
|
||||
AccessDenied
|
||||
}
|
||||
|
||||
|
||||
public static class StringArrayExtensions
|
||||
{
|
||||
public static string[] SortLikeWindows(this string[] array)
|
||||
{
|
||||
if (array == null) return null;
|
||||
if (array.Length == 0) return array;
|
||||
|
||||
Array.Sort(array, new WindowsFileNameComparer());
|
||||
return array;
|
||||
}
|
||||
|
||||
public static string[] SortLikeWindowsDescending(this string[] array)
|
||||
{
|
||||
if (array == null) return null;
|
||||
if (array.Length == 0) return array;
|
||||
|
||||
Array.Sort(array, new WindowsFileNameComparerDescending());
|
||||
return array;
|
||||
}
|
||||
|
||||
public static void SortLikeWindowsInPlace(this string[] array)
|
||||
{
|
||||
if (array == null || array.Length == 0) return;
|
||||
|
||||
Array.Sort(array, new WindowsFileNameComparer());
|
||||
}
|
||||
|
||||
public static void SortLikeWindowsDescendingInPlace(this string[] array)
|
||||
{
|
||||
if (array == null || array.Length == 0) return;
|
||||
|
||||
Array.Sort(array, new WindowsFileNameComparerDescending());
|
||||
}
|
||||
}
|
||||
|
||||
public class WindowsFileNameComparer : IComparer<string>
|
||||
{
|
||||
private static readonly Regex _regex = new Regex(@"(\d+|\D+)", RegexOptions.Compiled);
|
||||
private static readonly CompareInfo _compareInfo = CultureInfo.InvariantCulture.CompareInfo;
|
||||
|
||||
public int Compare(string? x, string? y)
|
||||
{
|
||||
if (x == null && y == null) return 0;
|
||||
if (x == null) return -1;
|
||||
if (y == null) return 1;
|
||||
if (ReferenceEquals(x, y)) return 0;
|
||||
|
||||
var partsX = _regex.Matches(x);
|
||||
var partsY = _regex.Matches(y);
|
||||
|
||||
int minLength = Math.Min(partsX.Count, partsY.Count);
|
||||
|
||||
for (int i = 0; i < minLength; i++)
|
||||
{
|
||||
string partX = partsX[i].Value;
|
||||
string partY = partsY[i].Value;
|
||||
|
||||
if (long.TryParse(partX, out long numX) && long.TryParse(partY, out long numY))
|
||||
{
|
||||
int comparison = numX.CompareTo(numY);
|
||||
if (comparison != 0) return comparison;
|
||||
}
|
||||
else
|
||||
{
|
||||
int comparison;
|
||||
if (ContainsChinese(partX) || ContainsChinese(partY))
|
||||
{
|
||||
comparison = _compareInfo.Compare(partX, partY, CompareOptions.IgnoreCase | CompareOptions.IgnoreNonSpace);
|
||||
}
|
||||
else
|
||||
{
|
||||
comparison = string.Compare(partX, partY, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
if (comparison != 0) return comparison;
|
||||
}
|
||||
}
|
||||
|
||||
return partsX.Count.CompareTo(partsY.Count);
|
||||
}
|
||||
|
||||
private static bool ContainsChinese(string text)
|
||||
{
|
||||
if (string.IsNullOrEmpty(text)) return false;
|
||||
|
||||
foreach (char c in text)
|
||||
{
|
||||
if (c >= 0x4E00 && c <= 0x9FFF)
|
||||
return true;
|
||||
if (c >= 0x3400 && c <= 0x4DBF)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public class WindowsFileNameComparerDescending : IComparer<string>
|
||||
{
|
||||
private static readonly WindowsFileNameComparer _ascendingComparer = new WindowsFileNameComparer();
|
||||
|
||||
public int Compare(string x, string y)
|
||||
{
|
||||
return _ascendingComparer.Compare(y, x);
|
||||
}
|
||||
}
|
||||
|
||||
public static class StringNaturalCompare
|
||||
{
|
||||
private static readonly WindowsFileNameComparer _comparer = new WindowsFileNameComparer();
|
||||
|
||||
public static int Compare(string x, string y)
|
||||
{
|
||||
return _comparer.Compare(x, y);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user