[feat] Video Group
This commit is contained in:
2
.idea/.idea.Abyss/.idea/dataSources.local.xml
generated
2
.idea/.idea.Abyss/.idea/dataSources.local.xml
generated
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="dataSourceStorageLocal" created-in="RD-252.25557.182">
|
||||
<component name="dataSourceStorageLocal" created-in="RD-252.26199.154">
|
||||
<data-source name="user" uuid="91acd9d8-5f8b-442f-9d50-17006d4e1ac7">
|
||||
<database-info product="SQLite" version="3.45.1" jdbc-version="4.2" driver-name="SQLite JDBC" driver-version="3.45.1.0" dbms="SQLITE" exact-version="3.45.1" exact-driver-version="3.45">
|
||||
<identifier-quote-string>"</identifier-quote-string>
|
||||
|
||||
@@ -499,7 +499,7 @@
|
||||
</routine>
|
||||
<schema id="191" parent="1" name="main">
|
||||
<Current>1</Current>
|
||||
<LastIntrospectionLocalTimestamp>2025-08-23.08:35:53</LastIntrospectionLocalTimestamp>
|
||||
<LastIntrospectionLocalTimestamp>2025-09-25.10:18:41</LastIntrospectionLocalTimestamp>
|
||||
</schema>
|
||||
<argument id="192" parent="16">
|
||||
<ArgumentDirection>R</ArgumentDirection>
|
||||
@@ -1590,45 +1590,72 @@
|
||||
<argument id="554" parent="190">
|
||||
<Position>1</Position>
|
||||
</argument>
|
||||
<table id="555" parent="191" name="User"/>
|
||||
<table id="555" parent="191" name="Users"/>
|
||||
<table id="556" parent="191" name="sqlite_master">
|
||||
<System>1</System>
|
||||
</table>
|
||||
<column id="557" parent="555" name="Name">
|
||||
<table id="557" parent="191" name="sqlite_sequence">
|
||||
<System>1</System>
|
||||
</table>
|
||||
<column id="558" parent="555" name="Uuid">
|
||||
<AutoIncrement>1</AutoIncrement>
|
||||
<NotNull>1</NotNull>
|
||||
<Position>1</Position>
|
||||
<StoredType>varchar|0s</StoredType>
|
||||
</column>
|
||||
<column id="558" parent="555" name="Parent">
|
||||
<Position>2</Position>
|
||||
<StoredType>varchar|0s</StoredType>
|
||||
</column>
|
||||
<column id="559" parent="555" name="PublicKey">
|
||||
<Position>3</Position>
|
||||
<StoredType>varchar|0s</StoredType>
|
||||
</column>
|
||||
<column id="560" parent="555" name="Privilege">
|
||||
<Position>4</Position>
|
||||
<StoredType>integer|0s</StoredType>
|
||||
</column>
|
||||
<column id="561" parent="556" name="type">
|
||||
<column id="559" parent="555" name="Username">
|
||||
<NotNull>1</NotNull>
|
||||
<Position>2</Position>
|
||||
<StoredType>varchar|0s</StoredType>
|
||||
</column>
|
||||
<column id="560" parent="555" name="ParentId">
|
||||
<NotNull>1</NotNull>
|
||||
<Position>3</Position>
|
||||
<StoredType>integer|0s</StoredType>
|
||||
</column>
|
||||
<column id="561" parent="555" name="PublicKey">
|
||||
<NotNull>1</NotNull>
|
||||
<Position>4</Position>
|
||||
<StoredType>varchar|0s</StoredType>
|
||||
</column>
|
||||
<column id="562" parent="555" name="Privilege">
|
||||
<NotNull>1</NotNull>
|
||||
<Position>5</Position>
|
||||
<StoredType>integer|0s</StoredType>
|
||||
</column>
|
||||
<index id="563" parent="555" name="Users_Username">
|
||||
<ColNames>Username</ColNames>
|
||||
<Unique>1</Unique>
|
||||
</index>
|
||||
<key id="564" parent="555">
|
||||
<ColNames>Uuid</ColNames>
|
||||
<Primary>1</Primary>
|
||||
</key>
|
||||
<column id="565" parent="556" name="type">
|
||||
<Position>1</Position>
|
||||
<StoredType>TEXT|0s</StoredType>
|
||||
</column>
|
||||
<column id="562" parent="556" name="name">
|
||||
<column id="566" parent="556" name="name">
|
||||
<Position>2</Position>
|
||||
<StoredType>TEXT|0s</StoredType>
|
||||
</column>
|
||||
<column id="563" parent="556" name="tbl_name">
|
||||
<column id="567" parent="556" name="tbl_name">
|
||||
<Position>3</Position>
|
||||
<StoredType>TEXT|0s</StoredType>
|
||||
</column>
|
||||
<column id="564" parent="556" name="rootpage">
|
||||
<column id="568" parent="556" name="rootpage">
|
||||
<Position>4</Position>
|
||||
<StoredType>INT|0s</StoredType>
|
||||
</column>
|
||||
<column id="565" parent="556" name="sql">
|
||||
<column id="569" parent="556" name="sql">
|
||||
<Position>5</Position>
|
||||
<StoredType>TEXT|0s</StoredType>
|
||||
</column>
|
||||
<column id="570" parent="557" name="name">
|
||||
<Position>1</Position>
|
||||
</column>
|
||||
<column id="571" parent="557" name="seq">
|
||||
<Position>2</Position>
|
||||
</column>
|
||||
</database-model>
|
||||
</dataSource>
|
||||
6
.idea/.idea.Abyss/.idea/sqldialects.xml
generated
Normal file
6
.idea/.idea.Abyss/.idea/sqldialects.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="SqlDialectMappings">
|
||||
<file url="file://$PROJECT_DIR$/Abyss/Components/Services/ResourceDatabaseService.cs" dialect="GenericSQL" />
|
||||
</component>
|
||||
</project>
|
||||
43
.idea/.idea.Abyss/.idea/workspace.xml
generated
43
.idea/.idea.Abyss/.idea/workspace.xml
generated
@@ -10,7 +10,15 @@
|
||||
</component>
|
||||
<component name="ChangeListManager">
|
||||
<list default="true" id="bf317275-3039-49bb-a475-725a800a0cce" name="Changes" comment="">
|
||||
<change afterPath="$PROJECT_DIR$/Abyss/Misc/StringClusterer.cs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/.idea/.idea.Abyss/.idea/dataSources.local.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/.idea.Abyss/.idea/dataSources.local.xml" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/.idea/.idea.Abyss/.idea/dataSources/91acd9d8-5f8b-442f-9d50-17006d4e1ac7.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/.idea.Abyss/.idea/dataSources/91acd9d8-5f8b-442f-9d50-17006d4e1ac7.xml" 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/VideoController.cs" beforeDir="false" afterPath="$PROJECT_DIR$/Abyss/Components/Controllers/Media/VideoController.cs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Abyss/Components/Services/IndexService.cs" beforeDir="false" afterPath="$PROJECT_DIR$/Abyss/Components/Services/IndexService.cs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Abyss/Model/Video.cs" beforeDir="false" afterPath="$PROJECT_DIR$/Abyss/Model/Video.cs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Abyss/Program.cs" beforeDir="false" afterPath="$PROJECT_DIR$/Abyss/Program.cs" afterDir="false" />
|
||||
</list>
|
||||
<option name="SHOW_DIALOG" value="false" />
|
||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||
@@ -28,12 +36,16 @@
|
||||
<setting file="file://$APPLICATION_CONFIG_DIR$/resharper-host/DecompilerCache/decompiler/457530be4752476295767457c3639889d1a000/25/817def70/ConfiguredValueTaskAwaitable`1.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/af/aac0eaa5/ExceptionDispatchInfo.cs" root0="FORCE_HIGHLIGHTING" />
|
||||
<setting file="file://$APPLICATION_CONFIG_DIR$/resharper-host/DecompilerCache/decompiler/457530be4752476295767457c3639889d1a000/b5/9de8e4ee/Index.cs" root0="SKIP_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/457530be4752476295767457c3639889d1a000/f3/fbf95091/SafeFileHandle.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/61fe11e9d86b4d2a9bd2b806929b7d381a400/a1/62750ee4/AsyncTableQuery`1.cs" root0="FORCE_HIGHLIGHTING" />
|
||||
<setting file="file://$APPLICATION_CONFIG_DIR$/resharper-host/DecompilerCache/decompiler/61fe11e9d86b4d2a9bd2b806929b7d381a400/e9/67f4a40e/SQLiteAsyncConnection.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" />
|
||||
<setting file="file://$PROJECT_DIR$/Abyss/Components/Controllers/AbyssController.cs" root0="FORCE_HIGHLIGHTING" />
|
||||
<setting file="file://$PROJECT_DIR$/Abyss/Components/Controllers/Media/IndexController.cs" root0="FORCE_HIGHLIGHTING" />
|
||||
<setting file="file://$PROJECT_DIR$/Abyss/Components/Controllers/Media/LiveController.cs" root0="FORCE_HIGHLIGHTING" />
|
||||
<setting file="file://$PROJECT_DIR$/Abyss/Components/Controllers/Middleware/BadRequestExceptionMiddleware.cs" root0="FORCE_HIGHLIGHTING" />
|
||||
<setting file="file://$PROJECT_DIR$/Abyss/Components/Controllers/Security/RootController.cs" root0="FORCE_HIGHLIGHTING" />
|
||||
@@ -41,6 +53,8 @@
|
||||
<setting file="file://$PROJECT_DIR$/Abyss/Components/Controllers/Task/TaskController.cs" root0="FORCE_HIGHLIGHTING" />
|
||||
<setting file="file://$PROJECT_DIR$/Abyss/Components/Services/AbyssService.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/IndexService.cs" root0="FORCE_HIGHLIGHTING" />
|
||||
<setting file="file://$PROJECT_DIR$/Abyss/Components/Services/ResourceDatabaseService.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/TaskService.cs" root0="FORCE_HIGHLIGHTING" />
|
||||
<setting file="file://$PROJECT_DIR$/Abyss/Components/Services/UserService.cs" root0="FORCE_HIGHLIGHTING" />
|
||||
@@ -48,17 +62,25 @@
|
||||
<setting file="file://$PROJECT_DIR$/Abyss/Components/Tools/AbyssStream.cs" root0="FORCE_HIGHLIGHTING" />
|
||||
<setting file="file://$PROJECT_DIR$/Abyss/Components/Tools/HttpHelper.cs" root0="FORCE_HIGHLIGHTING" />
|
||||
<setting file="file://$PROJECT_DIR$/Abyss/Components/Tools/HttpReader.cs" root0="FORCE_HIGHLIGHTING" />
|
||||
<setting file="file://$PROJECT_DIR$/Abyss/Misc/StringClusterer.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/Index.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" />
|
||||
<setting file="file://$PROJECT_DIR$/Abyss/Model/TaskCreation.cs" root0="FORCE_HIGHLIGHTING" />
|
||||
<setting file="file://$PROJECT_DIR$/Abyss/Model/User.cs" root0="FORCE_HIGHLIGHTING" />
|
||||
<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="mock:///home/acite/AciteProjects/Abyss/Abyss/Program.cs" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///home/acite/AciteProjects/Abyss/Abyss/Program.cs" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///home/acite/AciteProjects/Abyss/Abyss/Program.cs" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///home/acite/AciteProjects/Abyss/Abyss/Program.cs" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///home/acite/AciteProjects/Abyss/Abyss/Program.cs" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///home/acite/AciteProjects/Abyss/Abyss/Program.cs" root0="SKIP_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" />
|
||||
@@ -85,7 +107,7 @@
|
||||
"RunOnceActivity.ShowReadmeOnStart": "true",
|
||||
"RunOnceActivity.TerminalTabsStorage.copyFrom.TerminalArrangementManager.252": "true",
|
||||
"RunOnceActivity.git.unshallow": "true",
|
||||
"XThreadsFramesViewSplitterKey": "0.30266345",
|
||||
"XThreadsFramesViewSplitterKey": "0.55813956",
|
||||
"git-widget-placeholder": "main",
|
||||
"last_opened_file_path": "/home/acite/embd/WebProjects/Abyss/README.md",
|
||||
"node.js.detected.package.eslint": "true",
|
||||
@@ -97,7 +119,7 @@
|
||||
"vue.rearranger.settings.migration": "true"
|
||||
}
|
||||
}</component>
|
||||
<component name="RunManager" selected="Publish to folder.Publish Abyss to folder">
|
||||
<component name="RunManager" selected=".NET Launch Settings Profile.Abyss: http">
|
||||
<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>
|
||||
@@ -229,6 +251,10 @@
|
||||
<workItem from="1758350848039" duration="946000" />
|
||||
<workItem from="1758352441563" duration="281000" />
|
||||
<workItem from="1758599755722" duration="14000" />
|
||||
<workItem from="1758767744733" duration="12501000" />
|
||||
<workItem from="1758794950242" duration="9381000" />
|
||||
<workItem from="1758814543368" duration="642000" />
|
||||
<workItem from="1758815224532" duration="297000" />
|
||||
</task>
|
||||
<servers />
|
||||
</component>
|
||||
@@ -278,6 +304,19 @@
|
||||
<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/Program.cs</url>
|
||||
<line>31</line>
|
||||
<properties documentPath="$PROJECT_DIR$/Abyss/Program.cs" containingFunctionPresentation="Method 'Main'">
|
||||
<startOffsets>
|
||||
<option value="1008" />
|
||||
</startOffsets>
|
||||
<endOffsets>
|
||||
<option value="1062" />
|
||||
</endOffsets>
|
||||
</properties>
|
||||
<option name="timeStamp" value="4" />
|
||||
</line-breakpoint>
|
||||
</breakpoints>
|
||||
</breakpoint-manager>
|
||||
</component>
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AExceptionDispatchInfo_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2025_002E2_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F457530be4752476295767457c3639889d1a000_003Faf_003Faac0eaa5_003FExceptionDispatchInfo_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||
<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_003ASafeFileHandle_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2025_002E2_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F457530be4752476295767457c3639889d1a000_003Ff3_003Ffbf95091_003FSafeFileHandle_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_003ASQLiteAsyncConnection_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2025_002E2_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F61fe11e9d86b4d2a9bd2b806929b7d381a400_003Fe9_003F67f4a40e_003FSQLiteAsyncConnection_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>
|
||||
|
||||
@@ -46,19 +46,7 @@ public class VideoController(ILogger<VideoController> logger, ResourceService rs
|
||||
var r = await rs.Query(d, token, Ip);
|
||||
if (r == null) return StatusCode(401, new { message = "Unauthorized" });
|
||||
|
||||
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());
|
||||
return Ok(r);
|
||||
}
|
||||
|
||||
[HttpGet("{klass}/{id}")]
|
||||
|
||||
@@ -9,10 +9,10 @@ public class IndexService: IAsyncDisposable
|
||||
private bool _disposed;
|
||||
|
||||
|
||||
private IndexService(string dbPath)
|
||||
public IndexService(ConfigureService cs)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(dbPath)) throw new ArgumentNullException(nameof(dbPath));
|
||||
_db = new SQLiteAsyncConnection(dbPath);
|
||||
if (string.IsNullOrWhiteSpace(cs.IndexDatabase)) throw new ArgumentNullException(nameof(cs.IndexDatabase));
|
||||
_db = new SQLiteAsyncConnection(cs.IndexDatabase);
|
||||
|
||||
_db.CreateTableAsync<Index>().Wait();
|
||||
EnsureRootExistsAsync().Wait();
|
||||
|
||||
244
Abyss/Misc/StringClusterer.cs
Normal file
244
Abyss/Misc/StringClusterer.cs
Normal file
@@ -0,0 +1,244 @@
|
||||
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace Abyss.Misc;
|
||||
|
||||
public static class StringClusterer
|
||||
{
|
||||
public static Dictionary<string, List<string>> Cluster(
|
||||
string[] inputs,
|
||||
double mergeThreshold = 0.20
|
||||
)
|
||||
{
|
||||
return Cluster(inputs, s => s, mergeThreshold);
|
||||
}
|
||||
|
||||
public static Dictionary<string, List<T>> Cluster<T>(
|
||||
IEnumerable<T> inputs,
|
||||
Func<T, string> selector,
|
||||
double mergeThreshold = 0.20
|
||||
)
|
||||
{
|
||||
if (inputs == null) throw new ArgumentNullException(nameof(inputs));
|
||||
if (selector == null) throw new ArgumentNullException(nameof(selector));
|
||||
|
||||
var items = inputs.Select(x => new Item(selector(x), x)).ToList();
|
||||
|
||||
var groups = new Dictionary<string, Group>(StringComparer.OrdinalIgnoreCase);
|
||||
foreach (var it in items)
|
||||
{
|
||||
if (!groups.TryGetValue(it.KeyNorm, out var g))
|
||||
{
|
||||
g = new Group(it.KeyNorm);
|
||||
groups[it.KeyNorm] = g;
|
||||
}
|
||||
g.Items.Add(it);
|
||||
}
|
||||
|
||||
var keys = groups.Keys.ToList();
|
||||
var uf = new UnionFind(keys.Count);
|
||||
for (int i = 0; i < keys.Count; i++)
|
||||
{
|
||||
for (int j = i + 1; j < keys.Count; j++)
|
||||
{
|
||||
string k1 = keys[i], k2 = keys[j];
|
||||
int maxLen = Math.Max(k1.Length, k2.Length);
|
||||
if (maxLen == 0) continue;
|
||||
int lenDiff = Math.Abs(k1.Length - k2.Length);
|
||||
if (lenDiff > Math.Max(2, (int)Math.Ceiling(maxLen * 0.5))) continue;
|
||||
|
||||
double distNorm = (double)Levenshtein(k1, k2) / maxLen;
|
||||
if (distNorm <= mergeThreshold && CompatibleForMerge(groups[k1], groups[k2]))
|
||||
{
|
||||
uf.Union(i, j);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var merged = new Dictionary<int, List<Group>>();
|
||||
for (int i = 0; i < keys.Count; i++)
|
||||
{
|
||||
int root = uf.Find(i);
|
||||
if (!merged.TryGetValue(root, out var list))
|
||||
{
|
||||
list = new List<Group>();
|
||||
merged[root] = list;
|
||||
}
|
||||
list.Add(groups[keys[i]]);
|
||||
}
|
||||
|
||||
var result = new Dictionary<string, List<T>>();
|
||||
foreach (var kv in merged)
|
||||
{
|
||||
var combinedItems = kv.Value.SelectMany(g => g.Items).ToList();
|
||||
var members = combinedItems.Select(it => it.Original).ToList();
|
||||
|
||||
var uniqueMembers = new List<T>();
|
||||
var seen = new HashSet<string>();
|
||||
foreach (var it in combinedItems)
|
||||
if (seen.Add(it.Original)) uniqueMembers.Add((T)it.Payload);
|
||||
|
||||
string rawPrefix = LongestCommonPrefix(members);
|
||||
string groupName = TrimToTokenBoundary(rawPrefix);
|
||||
groupName = Regex.Replace(groupName, @"[\s_\-\.]+$", "");
|
||||
|
||||
result[groupName] = uniqueMembers;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static bool CompatibleForMerge(Group g1, Group g2)
|
||||
{
|
||||
if (g1.HasAnyAlphaTokenCountGreaterThanOne() != g2.HasAnyAlphaTokenCountGreaterThanOne())
|
||||
return false;
|
||||
|
||||
if (g1.HasTrailingNumber() != g2.HasTrailingNumber())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#region Helpers & Internal Types
|
||||
private class Item
|
||||
{
|
||||
public string Original { get; }
|
||||
public string[] Tokens { get; }
|
||||
public string KeyOriginal { get; }
|
||||
public string KeyNorm { get; }
|
||||
public int AlphaTokenCount { get; }
|
||||
public bool EndsWithNumber { get; }
|
||||
public object Payload { get; }
|
||||
|
||||
public Item(string original, object payload = null)
|
||||
{
|
||||
Original = original;
|
||||
Payload = payload ?? original;
|
||||
Tokens = TokenizeAlphaNum(Original).ToArray();
|
||||
EndsWithNumber = Tokens.Length > 0 && Regex.IsMatch(Tokens.Last(), "^[0-9]+$");
|
||||
var alphaTokens = Tokens.Where(t => Regex.IsMatch(t, "^[A-Za-z]+$")).ToList();
|
||||
AlphaTokenCount = alphaTokens.Count;
|
||||
|
||||
string candidate;
|
||||
if (EndsWithNumber && alphaTokens.Count >= 1)
|
||||
candidate = alphaTokens.Last();
|
||||
else if (alphaTokens.Count > 0)
|
||||
candidate = alphaTokens.OrderByDescending(t => t.Length).First();
|
||||
else if (Tokens.Length > 0)
|
||||
candidate = Tokens[0];
|
||||
else
|
||||
candidate = Original.Trim();
|
||||
|
||||
KeyOriginal = candidate;
|
||||
KeyNorm = NormalizeKey(candidate);
|
||||
}
|
||||
|
||||
|
||||
public static IEnumerable<string> TokenizeAlphaNum(string s)
|
||||
{
|
||||
if (string.IsNullOrEmpty(s)) yield break;
|
||||
var matches = Regex.Matches(s, @"[\p{IsCJKUnifiedIdeographs}\p{IsHiragana}\p{IsKatakana}]+|[A-Za-z]+|[0-9]+");
|
||||
foreach (Match m in matches) yield return m.Value;
|
||||
}
|
||||
}
|
||||
|
||||
private class Group
|
||||
{
|
||||
public string KeyNorm { get; }
|
||||
public List<Item> Items { get; } = new List<Item>();
|
||||
|
||||
public Group(string keyNorm) { KeyNorm = keyNorm; }
|
||||
|
||||
public bool HasAnyAlphaTokenCountGreaterThanOne()
|
||||
=> Items.Any(it => it.AlphaTokenCount > 1);
|
||||
|
||||
public bool HasTrailingNumber()
|
||||
=> Items.Any(it => it.EndsWithNumber);
|
||||
|
||||
public string RepresentativeOriginal()
|
||||
=> Items.Select(i => i.KeyOriginal).FirstOrDefault() ?? KeyNorm;
|
||||
}
|
||||
|
||||
private static string NormalizeKey(string s)
|
||||
{
|
||||
if (string.IsNullOrEmpty(s)) return string.Empty;
|
||||
string formD = s.Normalize(NormalizationForm.FormD);
|
||||
var sb = new StringBuilder();
|
||||
foreach (var ch in formD)
|
||||
{
|
||||
var uc = CharUnicodeInfo.GetUnicodeCategory(ch);
|
||||
if (uc == UnicodeCategory.NonSpacingMark) continue;
|
||||
if (char.IsLetterOrDigit(ch)) sb.Append(char.ToLowerInvariant(ch));
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
private static int Levenshtein(string a, string b)
|
||||
{
|
||||
int n = a.Length, m = b.Length;
|
||||
if (n == 0) return m;
|
||||
if (m == 0) return n;
|
||||
var d = new int[n + 1, m + 1];
|
||||
for (int i = 0; i <= n; i++) d[i, 0] = i;
|
||||
for (int j = 0; j <= m; j++) d[0, j] = j;
|
||||
for (int i = 1; i <= n; i++)
|
||||
{
|
||||
for (int j = 1; j <= m; j++)
|
||||
{
|
||||
int cost = (a[i - 1] == b[j - 1]) ? 0 : 1;
|
||||
d[i, j] = Math.Min(
|
||||
Math.Min(d[i - 1, j] + 1, d[i, j - 1] + 1),
|
||||
d[i - 1, j - 1] + cost
|
||||
);
|
||||
}
|
||||
}
|
||||
return d[n, m];
|
||||
}
|
||||
|
||||
private class UnionFind
|
||||
{
|
||||
private int[] _p;
|
||||
public UnionFind(int n) { _p = Enumerable.Range(0, n).ToArray(); }
|
||||
public int Find(int x) { return _p[x] == x ? x : (_p[x] = Find(_p[x])); }
|
||||
public void Union(int a, int b) { a = Find(a); b = Find(b); if (a != b) _p[b] = a; }
|
||||
}
|
||||
|
||||
private static string LongestCommonPrefix(List<string> strs)
|
||||
{
|
||||
if (strs.Count == 0) return string.Empty;
|
||||
string prefix = strs[0];
|
||||
foreach (var s in strs)
|
||||
{
|
||||
int len = Math.Min(prefix.Length, s.Length);
|
||||
int i = 0;
|
||||
while (i < len && prefix[i] == s[i]) i++;
|
||||
prefix = prefix.Substring(0, i);
|
||||
if (prefix == string.Empty) break;
|
||||
}
|
||||
return prefix;
|
||||
}
|
||||
|
||||
private static string TrimToTokenBoundary(string prefix)
|
||||
{
|
||||
if (string.IsNullOrEmpty(prefix)) return string.Empty;
|
||||
|
||||
var boundary = new Regex(@"[\s0-9_\-\.]");
|
||||
int lastBoundary = -1;
|
||||
|
||||
for (int i = 0; i < prefix.Length; i++)
|
||||
{
|
||||
if (boundary.IsMatch(prefix[i].ToString()))
|
||||
lastBoundary = i;
|
||||
}
|
||||
|
||||
if (lastBoundary >= 0)
|
||||
{
|
||||
return prefix.Substring(0, lastBoundary).TrimEnd();
|
||||
}
|
||||
|
||||
return prefix;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
@@ -9,4 +9,5 @@ public class Video
|
||||
public bool star;
|
||||
public uint like;
|
||||
public string author;
|
||||
public string? group;
|
||||
}
|
||||
@@ -1,8 +1,12 @@
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.RateLimiting;
|
||||
using Abyss.Components.Controllers.Middleware;
|
||||
using Abyss.Components.Controllers.Task;
|
||||
using Abyss.Components.Services;
|
||||
using Abyss.Misc;
|
||||
using Abyss.Model;
|
||||
using Microsoft.AspNetCore.RateLimiting;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Abyss;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user