[feat] Video Group

This commit is contained in:
acite
2025-09-25 23:54:09 +08:00
parent 76bdba1755
commit 79add11c08
10 changed files with 349 additions and 39 deletions

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <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"> <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"> <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>&quot;</identifier-quote-string> <identifier-quote-string>&quot;</identifier-quote-string>

View File

@@ -499,7 +499,7 @@
</routine> </routine>
<schema id="191" parent="1" name="main"> <schema id="191" parent="1" name="main">
<Current>1</Current> <Current>1</Current>
<LastIntrospectionLocalTimestamp>2025-08-23.08:35:53</LastIntrospectionLocalTimestamp> <LastIntrospectionLocalTimestamp>2025-09-25.10:18:41</LastIntrospectionLocalTimestamp>
</schema> </schema>
<argument id="192" parent="16"> <argument id="192" parent="16">
<ArgumentDirection>R</ArgumentDirection> <ArgumentDirection>R</ArgumentDirection>
@@ -1590,45 +1590,72 @@
<argument id="554" parent="190"> <argument id="554" parent="190">
<Position>1</Position> <Position>1</Position>
</argument> </argument>
<table id="555" parent="191" name="User"/> <table id="555" parent="191" name="Users"/>
<table id="556" parent="191" name="sqlite_master"> <table id="556" parent="191" name="sqlite_master">
<System>1</System> <System>1</System>
</table> </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> <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> <StoredType>integer|0s</StoredType>
</column> </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> <Position>1</Position>
<StoredType>TEXT|0s</StoredType> <StoredType>TEXT|0s</StoredType>
</column> </column>
<column id="562" parent="556" name="name"> <column id="566" parent="556" name="name">
<Position>2</Position> <Position>2</Position>
<StoredType>TEXT|0s</StoredType> <StoredType>TEXT|0s</StoredType>
</column> </column>
<column id="563" parent="556" name="tbl_name"> <column id="567" parent="556" name="tbl_name">
<Position>3</Position> <Position>3</Position>
<StoredType>TEXT|0s</StoredType> <StoredType>TEXT|0s</StoredType>
</column> </column>
<column id="564" parent="556" name="rootpage"> <column id="568" parent="556" name="rootpage">
<Position>4</Position> <Position>4</Position>
<StoredType>INT|0s</StoredType> <StoredType>INT|0s</StoredType>
</column> </column>
<column id="565" parent="556" name="sql"> <column id="569" parent="556" name="sql">
<Position>5</Position> <Position>5</Position>
<StoredType>TEXT|0s</StoredType> <StoredType>TEXT|0s</StoredType>
</column> </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> </database-model>
</dataSource> </dataSource>

6
.idea/.idea.Abyss/.idea/sqldialects.xml generated Normal file
View 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>

View File

@@ -10,7 +10,15 @@
</component> </component>
<component name="ChangeListManager"> <component name="ChangeListManager">
<list default="true" id="bf317275-3039-49bb-a475-725a800a0cce" name="Changes" comment=""> <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$/.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> </list>
<option name="SHOW_DIALOG" value="false" /> <option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" /> <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/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/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/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/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/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/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/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://$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/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/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/Middleware/BadRequestExceptionMiddleware.cs" root0="FORCE_HIGHLIGHTING" />
<setting file="file://$PROJECT_DIR$/Abyss/Components/Controllers/Security/RootController.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/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/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/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/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/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/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/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/HttpHelper.cs" root0="FORCE_HIGHLIGHTING" />
<setting file="file://$PROJECT_DIR$/Abyss/Components/Tools/HttpReader.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/Bookmark.cs" root0="FORCE_HIGHLIGHTING" />
<setting file="file://$PROJECT_DIR$/Abyss/Model/ChallengeResponse.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/Chip.cs" root0="FORCE_HIGHLIGHTING" />
<setting file="file://$PROJECT_DIR$/Abyss/Model/Comic.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/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/ResourceAttribute.cs" root0="FORCE_HIGHLIGHTING" />
<setting file="file://$PROJECT_DIR$/Abyss/Model/Task.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/TaskCreation.cs" root0="FORCE_HIGHLIGHTING" />
<setting file="file://$PROJECT_DIR$/Abyss/Model/User.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/UserCreating.cs" root0="FORCE_HIGHLIGHTING" />
<setting file="file://$PROJECT_DIR$/Abyss/Model/Video.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" /> <setting file="file:///usr/lib/dotnet/sdk/9.0.109/Sdks/Microsoft.NET.Sdk/targets/Microsoft.NET.Sdk.targets" root0="FORCE_HIGHLIGHTING" />
</component> </component>
<component name="MetaFilesCheckinStateConfiguration" checkMetaFiles="true" /> <component name="MetaFilesCheckinStateConfiguration" checkMetaFiles="true" />
@@ -85,7 +107,7 @@
&quot;RunOnceActivity.ShowReadmeOnStart&quot;: &quot;true&quot;, &quot;RunOnceActivity.ShowReadmeOnStart&quot;: &quot;true&quot;,
&quot;RunOnceActivity.TerminalTabsStorage.copyFrom.TerminalArrangementManager.252&quot;: &quot;true&quot;, &quot;RunOnceActivity.TerminalTabsStorage.copyFrom.TerminalArrangementManager.252&quot;: &quot;true&quot;,
&quot;RunOnceActivity.git.unshallow&quot;: &quot;true&quot;, &quot;RunOnceActivity.git.unshallow&quot;: &quot;true&quot;,
&quot;XThreadsFramesViewSplitterKey&quot;: &quot;0.30266345&quot;, &quot;XThreadsFramesViewSplitterKey&quot;: &quot;0.55813956&quot;,
&quot;git-widget-placeholder&quot;: &quot;main&quot;, &quot;git-widget-placeholder&quot;: &quot;main&quot;,
&quot;last_opened_file_path&quot;: &quot;/home/acite/embd/WebProjects/Abyss/README.md&quot;, &quot;last_opened_file_path&quot;: &quot;/home/acite/embd/WebProjects/Abyss/README.md&quot;,
&quot;node.js.detected.package.eslint&quot;: &quot;true&quot;, &quot;node.js.detected.package.eslint&quot;: &quot;true&quot;,
@@ -97,7 +119,7 @@
&quot;vue.rearranger.settings.migration&quot;: &quot;true&quot; &quot;vue.rearranger.settings.migration&quot;: &quot;true&quot;
} }
}</component> }</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"> <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"> <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> <runtimes>
@@ -229,6 +251,10 @@
<workItem from="1758350848039" duration="946000" /> <workItem from="1758350848039" duration="946000" />
<workItem from="1758352441563" duration="281000" /> <workItem from="1758352441563" duration="281000" />
<workItem from="1758599755722" duration="14000" /> <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> </task>
<servers /> <servers />
</component> </component>
@@ -278,6 +304,19 @@
<properties exception="System.Threading.ThreadAbortException" breakIfHandledByOtherCode="false" displayValue="System.Threading.ThreadAbortException" /> <properties exception="System.Threading.ThreadAbortException" breakIfHandledByOtherCode="false" displayValue="System.Threading.ThreadAbortException" />
<option name="timeStamp" value="3" /> <option name="timeStamp" value="3" />
</breakpoint> </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> </breakpoints>
</breakpoint-manager> </breakpoint-manager>
</component> </component>

View File

@@ -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_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_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_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_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_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> <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>

View File

@@ -46,19 +46,7 @@ public class VideoController(ILogger<VideoController> logger, ResourceService rs
var r = await rs.Query(d, token, Ip); var r = await rs.Query(d, token, Ip);
if (r == null) return StatusCode(401, new { message = "Unauthorized" }); if (r == null) return StatusCode(401, new { message = "Unauthorized" });
var rv = r.Select(x => { return Helpers.SafePathCombine(VideoFolder, [klass, x, "summary.json"]); }).ToArray(); return Ok(r);
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}")] [HttpGet("{klass}/{id}")]

View File

@@ -9,10 +9,10 @@ public class IndexService: IAsyncDisposable
private bool _disposed; private bool _disposed;
private IndexService(string dbPath) public IndexService(ConfigureService cs)
{ {
if (string.IsNullOrWhiteSpace(dbPath)) throw new ArgumentNullException(nameof(dbPath)); if (string.IsNullOrWhiteSpace(cs.IndexDatabase)) throw new ArgumentNullException(nameof(cs.IndexDatabase));
_db = new SQLiteAsyncConnection(dbPath); _db = new SQLiteAsyncConnection(cs.IndexDatabase);
_db.CreateTableAsync<Index>().Wait(); _db.CreateTableAsync<Index>().Wait();
EnsureRootExistsAsync().Wait(); EnsureRootExistsAsync().Wait();

View 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
}

View File

@@ -9,4 +9,5 @@ public class Video
public bool star; public bool star;
public uint like; public uint like;
public string author; public string author;
public string? group;
} }

View File

@@ -1,8 +1,12 @@
using System.Text.RegularExpressions;
using System.Threading.RateLimiting; using System.Threading.RateLimiting;
using Abyss.Components.Controllers.Middleware; using Abyss.Components.Controllers.Middleware;
using Abyss.Components.Controllers.Task; using Abyss.Components.Controllers.Task;
using Abyss.Components.Services; using Abyss.Components.Services;
using Abyss.Misc;
using Abyss.Model;
using Microsoft.AspNetCore.RateLimiting; using Microsoft.AspNetCore.RateLimiting;
using Newtonsoft.Json;
namespace Abyss; namespace Abyss;