[feat] Ctl framework
This commit is contained in:
4
.gitignore
vendored
4
.gitignore
vendored
@@ -57,4 +57,6 @@ nunit-*.xml
|
||||
*.db
|
||||
|
||||
appsettings.json
|
||||
appsettings.Development.json
|
||||
appsettings.Development.json
|
||||
build/
|
||||
publish/
|
||||
|
||||
7
.idea/.idea.Abyss/.idea/dictionaries/project.xml
generated
Normal file
7
.idea/.idea.Abyss/.idea/dictionaries/project.xml
generated
Normal file
@@ -0,0 +1,7 @@
|
||||
<component name="ProjectDictionaryState">
|
||||
<dictionary name="project">
|
||||
<words>
|
||||
<w>abyssctl</w>
|
||||
</words>
|
||||
</dictionary>
|
||||
</component>
|
||||
121
.idea/.idea.Abyss/.idea/workspace.xml
generated
121
.idea/.idea.Abyss/.idea/workspace.xml
generated
@@ -4,15 +4,36 @@
|
||||
<projectFile profileName="http">Abyss/Abyss.csproj</projectFile>
|
||||
<projectFile profileName="https">Abyss/Abyss.csproj</projectFile>
|
||||
<projectFile>AbyssCli/AbyssCli.csproj</projectFile>
|
||||
<projectFile>abyssctl/abyssctl.csproj</projectFile>
|
||||
</component>
|
||||
<component name="AutoImportSettings">
|
||||
<option name="autoReloadType" value="SELECTIVE" />
|
||||
</component>
|
||||
<component name="ChangeListManager">
|
||||
<list default="true" id="bf317275-3039-49bb-a475-725a800a0cce" name="Changes" comment="">
|
||||
<change afterPath="$PROJECT_DIR$/Abyss/Components/Services/Admin/Attributes/Module.cs" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/Abyss/Components/Services/Admin/CtlService.cs" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/Abyss/Components/Services/Admin/Interfaces/IModule.cs" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/Abyss/Components/Services/Admin/Modules/HelloModule.cs" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/Abyss/Components/Services/Admin/Modules/VersionModule.cs" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/Abyss/Components/Static/SocketExtensions.cs" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/Abyss/Model/Admin/Ctl.cs" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/abyssctl/App/App.cs" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/abyssctl/App/Modules/HelloOptions.cs" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/abyssctl/App/Modules/VersionOptions.cs" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/abyssctl/Model/Ctl.cs" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/abyssctl/Static/SocketExtensions.cs" afterDir="false" />
|
||||
<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.sln" beforeDir="false" afterPath="$PROJECT_DIR$/Abyss.sln" 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/Abyss.csproj" beforeDir="false" afterPath="$PROJECT_DIR$/Abyss/Abyss.csproj" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Abyss/Components/Controllers/Security/UserController.cs" beforeDir="false" afterPath="$PROJECT_DIR$/Abyss/Components/Controllers/Security/UserController.cs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Abyss/Components/Services/Security/UserService.cs" beforeDir="false" afterPath="$PROJECT_DIR$/Abyss/Components/Services/Security/UserService.cs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Abyss/Components/Controllers/Task/TaskController.cs" beforeDir="false" afterPath="$PROJECT_DIR$/Abyss/Components/Controllers/Task/TaskController.cs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Abyss/Components/Services/Media/ComicService.cs" beforeDir="false" afterPath="$PROJECT_DIR$/Abyss/Components/Services/Media/ComicService.cs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Abyss/Components/Services/Media/TaskService.cs" beforeDir="false" afterPath="$PROJECT_DIR$/Abyss/Components/Services/Media/TaskService.cs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Abyss/Components/Services/Media/VideoService.cs" beforeDir="false" afterPath="$PROJECT_DIR$/Abyss/Components/Services/Media/VideoService.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" />
|
||||
@@ -34,6 +55,7 @@
|
||||
<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/61241bc83d094fe6ac4acdfe094b2b7f1e000/d9/09284666/ServiceProviderServiceExtensions.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" />
|
||||
@@ -45,6 +67,11 @@
|
||||
<setting file="file://$PROJECT_DIR$/Abyss/Components/Controllers/Security/RootController.cs" root0="FORCE_HIGHLIGHTING" />
|
||||
<setting file="file://$PROJECT_DIR$/Abyss/Components/Controllers/Security/UserController.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/Admin/Attributes/Module.cs" root0="FORCE_HIGHLIGHTING" />
|
||||
<setting file="file://$PROJECT_DIR$/Abyss/Components/Services/Admin/CtlService.cs" root0="FORCE_HIGHLIGHTING" />
|
||||
<setting file="file://$PROJECT_DIR$/Abyss/Components/Services/Admin/Interfaces/IModule.cs" root0="FORCE_HIGHLIGHTING" />
|
||||
<setting file="file://$PROJECT_DIR$/Abyss/Components/Services/Admin/Modules/HelloModule.cs" root0="FORCE_HIGHLIGHTING" />
|
||||
<setting file="file://$PROJECT_DIR$/Abyss/Components/Services/Admin/Modules/VersionModule.cs" root0="FORCE_HIGHLIGHTING" />
|
||||
<setting file="file://$PROJECT_DIR$/Abyss/Components/Services/Media/ComicService.cs" root0="FORCE_HIGHLIGHTING" />
|
||||
<setting file="file://$PROJECT_DIR$/Abyss/Components/Services/Media/IndexService.cs" root0="FORCE_HIGHLIGHTING" />
|
||||
<setting file="file://$PROJECT_DIR$/Abyss/Components/Services/Media/ResourceDatabaseService.cs" root0="FORCE_HIGHLIGHTING" />
|
||||
@@ -55,10 +82,12 @@
|
||||
<setting file="file://$PROJECT_DIR$/Abyss/Components/Services/Security/AbyssService.cs" root0="FORCE_HIGHLIGHTING" />
|
||||
<setting file="file://$PROJECT_DIR$/Abyss/Components/Services/Security/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/Static/SocketExtensions.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/HttpReader.cs" root0="FORCE_HIGHLIGHTING" />
|
||||
<setting file="file://$PROJECT_DIR$/Abyss/Misc/StringClusterer.cs" root0="FORCE_HIGHLIGHTING" />
|
||||
<setting file="file://$PROJECT_DIR$/Abyss/Model/Admin/Ctl.cs" root0="FORCE_HIGHLIGHTING" />
|
||||
<setting file="file://$PROJECT_DIR$/Abyss/Model/Media/Bookmark.cs" root0="FORCE_HIGHLIGHTING" />
|
||||
<setting file="file://$PROJECT_DIR$/Abyss/Model/Media/Chip.cs" root0="FORCE_HIGHLIGHTING" />
|
||||
<setting file="file://$PROJECT_DIR$/Abyss/Model/Media/Comic.cs" root0="FORCE_HIGHLIGHTING" />
|
||||
@@ -71,7 +100,10 @@
|
||||
<setting file="file://$PROJECT_DIR$/Abyss/Model/Security/ChallengeResponse.cs" root0="FORCE_HIGHLIGHTING" />
|
||||
<setting file="file://$PROJECT_DIR$/Abyss/Model/Security/User.cs" root0="FORCE_HIGHLIGHTING" />
|
||||
<setting file="file://$PROJECT_DIR$/Abyss/Model/Security/UserCreating.cs" 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" />
|
||||
<setting file="file://$PROJECT_DIR$/abyssctl/App/App.cs" root0="FORCE_HIGHLIGHTING" />
|
||||
<setting file="file://$PROJECT_DIR$/abyssctl/App/Modules/HelloOptions.cs" root0="FORCE_HIGHLIGHTING" />
|
||||
<setting file="file://$PROJECT_DIR$/abyssctl/App/Modules/VersionOptions.cs" root0="FORCE_HIGHLIGHTING" />
|
||||
<setting file="file://$PROJECT_DIR$/abyssctl/Program.cs" root0="FORCE_HIGHLIGHTING" />
|
||||
</component>
|
||||
<component name="MetaFilesCheckinStateConfiguration" checkMetaFiles="true" />
|
||||
<component name="ProblemsViewState">
|
||||
@@ -85,51 +117,44 @@
|
||||
<option name="hideEmptyMiddlePackages" value="true" />
|
||||
<option name="showLibraryContents" value="true" />
|
||||
</component>
|
||||
<component name="PropertiesComponent">{
|
||||
"keyToString": {
|
||||
".NET Launch Settings Profile.Abyss: http.executor": "Run",
|
||||
".NET Launch Settings Profile.Abyss: https.executor": "Debug",
|
||||
".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.55813956",
|
||||
"git-widget-placeholder": "main",
|
||||
"last_opened_file_path": "/home/acite/AciteProjects/Abyss/README.md",
|
||||
"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": "com.jetbrains.python.configuration.PyActiveSdkModuleConfigurable",
|
||||
"vue.rearranger.settings.migration": "true"
|
||||
<component name="PropertiesComponent"><![CDATA[{
|
||||
"keyToString": {
|
||||
".NET Launch Settings Profile.Abyss: http.executor": "Debug",
|
||||
".NET Launch Settings Profile.Abyss: https.executor": "Debug",
|
||||
".NET Project.AbyssCli.executor": "Run",
|
||||
".NET Project.abyssctl.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.55813956",
|
||||
"git-widget-placeholder": "main",
|
||||
"last_opened_file_path": "/home/acite/AciteProjects/Abyss/README.md",
|
||||
"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": "com.jetbrains.python.configuration.PyActiveSdkModuleConfigurable",
|
||||
"vue.rearranger.settings.migration": "true"
|
||||
}
|
||||
}</component>
|
||||
<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>
|
||||
<item value="linux-x64" />
|
||||
</runtimes>
|
||||
</riderPublish>
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
<configuration name="Publish Abyss to folder" 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/publish" target_framework="net9.0" uuid_high="3690631506471504162" uuid_low="-4858628519588143325">
|
||||
}]]></component>
|
||||
<component name="RunManager" selected=".NET Launch Settings Profile.Abyss: http">
|
||||
<configuration name="Publish Abyss to folder" type="DotNetFolderPublish" factoryName="Publish to folder" singleton="false">
|
||||
<riderPublish configuration="Release" platform="Any CPU" produce_single_file="true" self_contained="true" target_folder="$PROJECT_DIR$/publish" target_framework="net9.0" uuid_high="3690631506471504162" uuid_low="-4858628519588143325">
|
||||
<runtimes>
|
||||
<item value="linux-arm64" />
|
||||
</runtimes>
|
||||
</riderPublish>
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
<configuration name="AbyssCli" type="DotNetProject" factoryName=".NET Project">
|
||||
<option name="EXE_PATH" value="" />
|
||||
<configuration name="abyssctl" type="DotNetProject" factoryName=".NET Project">
|
||||
<option name="EXE_PATH" value="$PROJECT_DIR$/build/net9.0/abyssctl" />
|
||||
<option name="PROGRAM_PARAMETERS" value="" />
|
||||
<option name="WORKING_DIRECTORY" value="" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/build/net9.0" />
|
||||
<option name="PASS_PARENT_ENVS" value="1" />
|
||||
<option name="USE_EXTERNAL_CONSOLE" value="0" />
|
||||
<option name="ENV_FILE_PATHS" value="" />
|
||||
@@ -139,12 +164,12 @@
|
||||
<option name="USE_MONO" value="0" />
|
||||
<option name="RUNTIME_ARGUMENTS" value="" />
|
||||
<option name="AUTO_ATTACH_CHILDREN" value="0" />
|
||||
<option name="PROJECT_PATH" value="$PROJECT_DIR$/AbyssCli/AbyssCli.csproj" />
|
||||
<option name="PROJECT_PATH" value="$PROJECT_DIR$/abyssctl/abyssctl.csproj" />
|
||||
<option name="PROJECT_EXE_PATH_TRACKING" value="1" />
|
||||
<option name="PROJECT_ARGUMENTS_TRACKING" value="1" />
|
||||
<option name="PROJECT_WORKING_DIRECTORY_TRACKING" value="1" />
|
||||
<option name="PROJECT_KIND" value="DotNetCore" />
|
||||
<option name="PROJECT_TFM" value="" />
|
||||
<option name="PROJECT_TFM" value="net9.0" />
|
||||
<method v="2">
|
||||
<option name="Build" />
|
||||
</method>
|
||||
@@ -167,9 +192,8 @@
|
||||
</configuration>
|
||||
<list>
|
||||
<item itemvalue=".NET Launch Settings Profile.Abyss: http" />
|
||||
<item itemvalue=".NET Project.AbyssCli" />
|
||||
<item itemvalue=".NET Project.abyssctl" />
|
||||
<item itemvalue="Publish to folder.Publish Abyss to folder" />
|
||||
<item itemvalue="Publish to folder.Publish Abyss to folder x86" />
|
||||
</list>
|
||||
</component>
|
||||
<component name="TaskManager">
|
||||
@@ -254,6 +278,17 @@
|
||||
<workItem from="1759314718830" duration="55000" />
|
||||
<workItem from="1759315721112" duration="82000" />
|
||||
<workItem from="1759398581423" duration="2195000" />
|
||||
<workItem from="1759401971386" duration="69000" />
|
||||
<workItem from="1759434890177" duration="183000" />
|
||||
<workItem from="1759508787637" duration="115000" />
|
||||
<workItem from="1759509008651" duration="2869000" />
|
||||
<workItem from="1759515879741" duration="297000" />
|
||||
<workItem from="1759516905127" duration="1451000" />
|
||||
<workItem from="1759519618552" duration="9000" />
|
||||
<workItem from="1759520741934" duration="642000" />
|
||||
<workItem from="1759551752441" duration="5836000" />
|
||||
<workItem from="1759561043616" duration="201000" />
|
||||
<workItem from="1759591584659" duration="6926000" />
|
||||
</task>
|
||||
<servers />
|
||||
</component>
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Abyss", "Abyss\Abyss.csproj", "{3337C1CD-2419-4922-BC92-AF1A825DDF23}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "abyssctl", "abyssctl\abyssctl.csproj", "{F6DEF111-0CAD-4DCC-8957-7EBAFCF3D2C4}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -12,5 +14,9 @@ Global
|
||||
{3337C1CD-2419-4922-BC92-AF1A825DDF23}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{3337C1CD-2419-4922-BC92-AF1A825DDF23}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{3337C1CD-2419-4922-BC92-AF1A825DDF23}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{F6DEF111-0CAD-4DCC-8957-7EBAFCF3D2C4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{F6DEF111-0CAD-4DCC-8957-7EBAFCF3D2C4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{F6DEF111-0CAD-4DCC-8957-7EBAFCF3D2C4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{F6DEF111-0CAD-4DCC-8957-7EBAFCF3D2C4}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
<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_003AServiceProviderServiceExtensions_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2025_002E2_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F61241bc83d094fe6ac4acdfe094b2b7f1e000_003Fd9_003F09284666_003FServiceProviderServiceExtensions_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>
|
||||
|
||||
@@ -6,6 +6,10 @@
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
|
||||
<OutputPath>../build/</OutputPath>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="K4os.Hash.xxHash" Version="1.0.8" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.8"/>
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace Abyss.Components.Controllers.Security;
|
||||
[ApiController]
|
||||
[Route("api/[controller]")]
|
||||
[EnableRateLimiting("Fixed")]
|
||||
public class UserController(UserService userService, ILogger<UserController> logger) : BaseController
|
||||
public class UserController(UserService userService) : BaseController
|
||||
{
|
||||
[HttpGet("{user}")]
|
||||
public async Task<IActionResult> Challenge(string user)
|
||||
|
||||
@@ -35,27 +35,26 @@ public class TaskController(ConfigureService config, TaskService taskService) :
|
||||
return Ok(JsonConvert.SerializeObject(r, Formatting.Indented));
|
||||
}
|
||||
|
||||
[HttpGet("{id}")]
|
||||
public async Task<IActionResult> GetTask(string id)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
[HttpPatch("{id}")]
|
||||
public async Task<IActionResult> PutChip(string id)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
[HttpPost("{id}")]
|
||||
public async Task<IActionResult> VerifyChip(string id)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
[HttpDelete("{id}")]
|
||||
public async Task<IActionResult> DeleteTask(string id)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
// [HttpGet("{id}")]
|
||||
// public async Task<IActionResult> GetTask(string id)
|
||||
// {
|
||||
// throw new NotImplementedException();
|
||||
// }
|
||||
//
|
||||
// [HttpPatch("{id}")]
|
||||
// public async Task<IActionResult> PutChip(string id)
|
||||
// {
|
||||
// throw new NotImplementedException();
|
||||
// }
|
||||
//
|
||||
// [HttpPost("{id}")]
|
||||
// public async Task<IActionResult> VerifyChip(string id)
|
||||
// {
|
||||
// throw new NotImplementedException();
|
||||
// }
|
||||
// [HttpDelete("{id}")]
|
||||
// public async Task<IActionResult> DeleteTask(string id)
|
||||
// {
|
||||
// throw new NotImplementedException();
|
||||
// }
|
||||
}
|
||||
29
Abyss/Components/Services/Admin/Attributes/Module.cs
Normal file
29
Abyss/Components/Services/Admin/Attributes/Module.cs
Normal file
@@ -0,0 +1,29 @@
|
||||
using System.Reflection;
|
||||
using Abyss.Components.Services.Admin.Interfaces;
|
||||
|
||||
namespace Abyss.Components.Services.Admin.Attributes;
|
||||
|
||||
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
|
||||
public class Module(int head) : Attribute
|
||||
{
|
||||
public int Head { get; } = head;
|
||||
|
||||
public static Type[] Modules
|
||||
{
|
||||
get
|
||||
{
|
||||
Assembly assembly = Assembly.GetExecutingAssembly();
|
||||
Type attributeType = typeof(Module);
|
||||
const string targetNamespace = "Abyss.Components.Services.Admin.Modules";
|
||||
|
||||
var moduleTypes = assembly.GetTypes()
|
||||
.Where(t => t is { IsClass: true, IsAbstract: false, IsInterface: false })
|
||||
.Where(t => t.Namespace == targetNamespace)
|
||||
.Where(t => typeof(IModule).IsAssignableFrom(t))
|
||||
.Where(t => t.IsDefined(attributeType, inherit: false))
|
||||
.ToArray();
|
||||
|
||||
return moduleTypes;
|
||||
}
|
||||
}
|
||||
}
|
||||
110
Abyss/Components/Services/Admin/CtlService.cs
Normal file
110
Abyss/Components/Services/Admin/CtlService.cs
Normal file
@@ -0,0 +1,110 @@
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
|
||||
using Abyss.Components.Static;
|
||||
using Abyss.Model.Admin;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
using System.Reflection;
|
||||
using Abyss.Components.Services.Admin.Interfaces;
|
||||
using Module = Abyss.Components.Services.Admin.Attributes.Module;
|
||||
|
||||
namespace Abyss.Components.Services.Admin;
|
||||
|
||||
public class CtlService(ILogger<CtlService> logger, IServiceProvider serviceProvider) : IHostedService
|
||||
{
|
||||
private readonly string _socketPath = "ctl.sock";
|
||||
|
||||
private Task? _executingTask;
|
||||
private CancellationTokenSource? _cts;
|
||||
private Dictionary<int, Type> _handlers = new();
|
||||
|
||||
public Task StartAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
var t = Module.Modules;
|
||||
foreach (var module in t)
|
||||
{
|
||||
var attr = module.GetCustomAttribute<Module>();
|
||||
if (attr != null)
|
||||
{
|
||||
_handlers[attr.Head] = module;
|
||||
}
|
||||
}
|
||||
|
||||
_cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
|
||||
_executingTask = ExecuteAsync(_cts.Token);
|
||||
return _executingTask.IsCompleted ? _executingTask : Task.CompletedTask;
|
||||
}
|
||||
|
||||
public async Task StopAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
if (_executingTask == null)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
_cts?.CancelAsync();
|
||||
}
|
||||
finally
|
||||
{
|
||||
await Task.WhenAny(_executingTask,
|
||||
Task.Delay(Timeout.Infinite, cancellationToken));
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ExecuteAsync(CancellationToken stoppingToken)
|
||||
{
|
||||
if (File.Exists(_socketPath))
|
||||
{
|
||||
File.Delete(_socketPath);
|
||||
}
|
||||
|
||||
var endPoint = new UnixDomainSocketEndPoint(_socketPath);
|
||||
|
||||
using var socket = new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.Unspecified);
|
||||
socket.Bind(endPoint);
|
||||
socket.Listen(5);
|
||||
|
||||
while (!stoppingToken.IsCancellationRequested)
|
||||
{
|
||||
try
|
||||
{
|
||||
var clientSocket = await socket.AcceptAsync(stoppingToken);
|
||||
_ = HandleClientAsync(clientSocket, stoppingToken);
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async Task HandleClientAsync(Socket clientSocket, CancellationToken stoppingToken)
|
||||
{
|
||||
async Task _400()
|
||||
{
|
||||
await clientSocket.WriteBase64Async(Ctl.MakeBase64(400, ["Bad Request"]), stoppingToken);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var s = Encoding.UTF8.GetString(
|
||||
Convert.FromBase64String(await clientSocket.ReadBase64Async(stoppingToken)));
|
||||
var json = JsonConvert.DeserializeObject<Ctl>(s);
|
||||
|
||||
if (json == null || !_handlers.TryGetValue(json.Head, out var handler))
|
||||
{
|
||||
await _400();
|
||||
return;
|
||||
}
|
||||
|
||||
var module = (serviceProvider.GetRequiredService(handler) as IModule)!;
|
||||
var r = await module.ExecuteAsync(json, stoppingToken);
|
||||
await clientSocket.WriteBase64Async(Ctl.MakeBase64(r.Head, r.Params), stoppingToken);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
logger.LogError(e, "Error while handling client connection");
|
||||
}
|
||||
}
|
||||
}
|
||||
8
Abyss/Components/Services/Admin/Interfaces/IModule.cs
Normal file
8
Abyss/Components/Services/Admin/Interfaces/IModule.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
using Abyss.Model.Admin;
|
||||
|
||||
namespace Abyss.Components.Services.Admin.Interfaces;
|
||||
|
||||
public interface IModule
|
||||
{
|
||||
public Task<Ctl> ExecuteAsync(Ctl request, CancellationToken ct);
|
||||
}
|
||||
18
Abyss/Components/Services/Admin/Modules/HelloModule.cs
Normal file
18
Abyss/Components/Services/Admin/Modules/HelloModule.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
using Abyss.Components.Services.Admin.Attributes;
|
||||
using Abyss.Components.Services.Admin.Interfaces;
|
||||
using Abyss.Model.Admin;
|
||||
|
||||
namespace Abyss.Components.Services.Admin.Modules;
|
||||
|
||||
[Module(100)]
|
||||
public class HelloModule: IModule
|
||||
{
|
||||
public async Task<Ctl> ExecuteAsync(Ctl request, CancellationToken ct)
|
||||
{
|
||||
return await Task.FromResult(new Ctl
|
||||
{
|
||||
Head = 200,
|
||||
Params = ["Hi"],
|
||||
});
|
||||
}
|
||||
}
|
||||
14
Abyss/Components/Services/Admin/Modules/VersionModule.cs
Normal file
14
Abyss/Components/Services/Admin/Modules/VersionModule.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using Abyss.Components.Services.Admin.Attributes;
|
||||
using Abyss.Components.Services.Admin.Interfaces;
|
||||
using Abyss.Model.Admin;
|
||||
|
||||
namespace Abyss.Components.Services.Admin.Modules;
|
||||
|
||||
[Module(101)]
|
||||
public class VersionModule: IModule
|
||||
{
|
||||
public async Task<Ctl> ExecuteAsync(Ctl request, CancellationToken ct)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
@@ -3,11 +3,10 @@ using Abyss.Components.Static;
|
||||
using Abyss.Model.Media;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Newtonsoft.Json;
|
||||
using Task = System.Threading.Tasks.Task;
|
||||
|
||||
namespace Abyss.Components.Services.Media;
|
||||
|
||||
public class ComicService(ILogger<ComicService> logger, ResourceService rs, ConfigureService config)
|
||||
public class ComicService(ResourceService rs, ConfigureService config)
|
||||
{
|
||||
public readonly string ImageFolder = Path.Combine(config.MediaRoot, "Images");
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace Abyss.Components.Services.Media;
|
||||
|
||||
|
||||
|
||||
public class TaskService(ILogger<TaskService> logger, ConfigureService config, ResourceService rs, UserService user)
|
||||
public class TaskService(ConfigureService config, ResourceService rs, UserService user)
|
||||
{
|
||||
public readonly string TaskFolder = Path.Combine(config.MediaRoot, "Tasks");
|
||||
public readonly string VideoFolder = Path.Combine(config.MediaRoot, "Videos");
|
||||
@@ -26,7 +26,7 @@ public class TaskService(ILogger<TaskService> logger, ConfigureService config, R
|
||||
foreach (var i in r ?? [])
|
||||
{
|
||||
var p = Helpers.SafePathCombine(TaskFolder, [i, "task.json"]);
|
||||
var c = JsonConvert.DeserializeObject<Task>(await System.IO.File.ReadAllTextAsync(p ?? ""));
|
||||
var c = JsonConvert.DeserializeObject<Task>(await File.ReadAllTextAsync(p ?? ""));
|
||||
|
||||
if(c?.Owner == u) s.Add(i);
|
||||
}
|
||||
@@ -50,7 +50,8 @@ public class TaskService(ILogger<TaskService> logger, ConfigureService config, R
|
||||
switch ((TaskType)creation.Type)
|
||||
{
|
||||
case TaskType.Image:
|
||||
return await CreateImageTask(token, ip, creation);
|
||||
throw new NotImplementedException();
|
||||
// return await CreateImageTask(token, ip, creation);
|
||||
case TaskType.Video:
|
||||
return await CreateVideoTask(token, ip, creation);
|
||||
default:
|
||||
@@ -105,10 +106,10 @@ public class TaskService(ILogger<TaskService> logger, ConfigureService config, R
|
||||
return r;
|
||||
}
|
||||
|
||||
private async Task<TaskCreationResponse?> CreateImageTask(string token, string ip, TaskCreation creation)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
// private async Task<TaskCreationResponse?> CreateImageTask(string token, string ip, TaskCreation creation)
|
||||
// {
|
||||
// throw new NotImplementedException();
|
||||
// }
|
||||
|
||||
public static uint GenerateUniqueId(string parentDirectory)
|
||||
{
|
||||
|
||||
@@ -7,7 +7,7 @@ using Newtonsoft.Json;
|
||||
|
||||
namespace Abyss.Components.Services.Media;
|
||||
|
||||
public class VideoService(ILogger<VideoService> logger, ResourceService rs, ConfigureService config)
|
||||
public class VideoService(ResourceService rs, ConfigureService config)
|
||||
{
|
||||
public readonly string VideoFolder = Path.Combine(config.MediaRoot, "Videos");
|
||||
|
||||
|
||||
51
Abyss/Components/Static/SocketExtensions.cs
Normal file
51
Abyss/Components/Static/SocketExtensions.cs
Normal file
@@ -0,0 +1,51 @@
|
||||
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
|
||||
namespace Abyss.Components.Static;
|
||||
|
||||
public static class SocketExtensions
|
||||
{
|
||||
public static async Task<string> ReadBase64Async(this Socket socket, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var buffer = new byte[4096];
|
||||
var sb = new StringBuilder();
|
||||
|
||||
while (true)
|
||||
{
|
||||
int bytesRead = await socket.ReceiveAsync(buffer, SocketFlags.None, cancellationToken).ConfigureAwait(false);
|
||||
if (bytesRead == 0)
|
||||
throw new SocketException((int)SocketError.ConnectionReset);
|
||||
|
||||
string chunk = Encoding.UTF8.GetString(buffer, 0, bytesRead);
|
||||
sb.Append(chunk);
|
||||
|
||||
int newlineIndex = sb.ToString().IndexOf('\n');
|
||||
if (newlineIndex >= 0)
|
||||
{
|
||||
string base64 = sb.ToString(0, newlineIndex).Trim();
|
||||
sb.Remove(0, newlineIndex + 1);
|
||||
return base64;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task WriteBase64Async(this Socket socket, string base64, CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(base64))
|
||||
throw new ArgumentException("Base64 string cannot be null or empty.", nameof(base64));
|
||||
|
||||
string message = base64 + "\n";
|
||||
byte[] data = Encoding.UTF8.GetBytes(message);
|
||||
|
||||
int totalSent = 0;
|
||||
while (totalSent < data.Length)
|
||||
{
|
||||
int sent = await socket.SendAsync(data.AsMemory(totalSent), SocketFlags.None, cancellationToken).ConfigureAwait(false);
|
||||
if (sent == 0)
|
||||
throw new SocketException((int)SocketError.ConnectionReset);
|
||||
|
||||
totalSent += sent;
|
||||
}
|
||||
}
|
||||
}
|
||||
19
Abyss/Model/Admin/Ctl.cs
Normal file
19
Abyss/Model/Admin/Ctl.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
using System.Text;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Abyss.Model.Admin;
|
||||
|
||||
public class Ctl
|
||||
{
|
||||
[JsonProperty("head")]
|
||||
public int Head { get; set; }
|
||||
|
||||
[JsonProperty("params")] public string[] Params { get; set; } = [];
|
||||
|
||||
public static string MakeBase64(int head, string[] param)
|
||||
{
|
||||
return Convert.ToBase64String(
|
||||
Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(new Ctl
|
||||
{ Head = head, Params = param })));
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,9 @@
|
||||
using System.Threading.RateLimiting;
|
||||
using Abyss.Components.Controllers.Middleware;
|
||||
using Abyss.Components.Controllers.Task;
|
||||
|
||||
using Abyss.Components.Services.Admin;
|
||||
using Abyss.Components.Services.Admin.Attributes;
|
||||
using Abyss.Components.Services.Admin.Modules;
|
||||
using Abyss.Components.Services.Media;
|
||||
using Abyss.Components.Services.Misc;
|
||||
using Abyss.Components.Services.Security;
|
||||
@@ -30,6 +32,12 @@ public class Program
|
||||
builder.Services.AddSingleton<VideoService>();
|
||||
builder.Services.AddSingleton<ComicService>();
|
||||
builder.Services.AddHostedService<AbyssService>();
|
||||
builder.Services.AddHostedService<CtlService>();
|
||||
|
||||
foreach (var t in Module.Modules)
|
||||
{
|
||||
builder.Services.AddTransient(t);
|
||||
}
|
||||
|
||||
builder.Services.AddRateLimiter(options =>
|
||||
{
|
||||
|
||||
49
abyssctl/App/App.cs
Normal file
49
abyssctl/App/App.cs
Normal file
@@ -0,0 +1,49 @@
|
||||
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
using abyssctl.App.Modules;
|
||||
using abyssctl.Model;
|
||||
using abyssctl.Static;
|
||||
using CommandLine;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace abyssctl.App;
|
||||
|
||||
public class App
|
||||
{
|
||||
private static readonly string SocketPath = "ctl.sock";
|
||||
|
||||
public static async Task<Ctl> CtlWriteRead(Ctl ctl)
|
||||
{
|
||||
var endPoint = new UnixDomainSocketEndPoint(SocketPath);
|
||||
using var socket = new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.Unspecified);
|
||||
try
|
||||
{
|
||||
await socket.ConnectAsync(endPoint);
|
||||
await socket.WriteBase64Async(Ctl.MakeBase64(ctl.Head, ctl.Params));
|
||||
var s = Encoding.UTF8.GetString(
|
||||
Convert.FromBase64String(await socket.ReadBase64Async()));
|
||||
return JsonConvert.DeserializeObject<Ctl>(s)!;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return new Ctl
|
||||
{
|
||||
Head = 500,
|
||||
Params = [e.Message]
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<int> RunAsync(string[] args)
|
||||
{
|
||||
return await Task.Run(() =>
|
||||
{
|
||||
return Parser.Default.ParseArguments<HelloOptions, VersionOptions>(args)
|
||||
.MapResult(
|
||||
(HelloOptions opt) => HelloOptions.Run(opt),
|
||||
(VersionOptions opt) => VersionOptions.Run(opt),
|
||||
_ => 1);
|
||||
});
|
||||
}
|
||||
}
|
||||
20
abyssctl/App/Modules/HelloOptions.cs
Normal file
20
abyssctl/App/Modules/HelloOptions.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
using abyssctl.Model;
|
||||
using CommandLine;
|
||||
|
||||
namespace abyssctl.App.Modules;
|
||||
|
||||
[Verb("hello", HelpText = "Say hello to abyss server")]
|
||||
public class HelloOptions
|
||||
{
|
||||
public static int Run(HelloOptions opts)
|
||||
{
|
||||
var r = App.CtlWriteRead(new Ctl
|
||||
{
|
||||
Head = 100,
|
||||
Params = []
|
||||
}).GetAwaiter().GetResult();
|
||||
Console.WriteLine($"Response Code: {r.Head}");
|
||||
Console.WriteLine($"Params: {string.Join(",", r.Params)}");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
13
abyssctl/App/Modules/VersionOptions.cs
Normal file
13
abyssctl/App/Modules/VersionOptions.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using CommandLine;
|
||||
|
||||
namespace abyssctl.App.Modules;
|
||||
|
||||
[Verb("ver", HelpText = "Get server version")]
|
||||
public class VersionOptions
|
||||
{
|
||||
public static int Run(VersionOptions opts)
|
||||
{
|
||||
Console.WriteLine("Version");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
19
abyssctl/Model/Ctl.cs
Normal file
19
abyssctl/Model/Ctl.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
using System.Text;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace abyssctl.Model;
|
||||
|
||||
public class Ctl
|
||||
{
|
||||
[JsonProperty("head")] public int Head { get; set; }
|
||||
|
||||
[JsonProperty("params")] public string[] Params { get; set; } = [];
|
||||
|
||||
public static string MakeBase64(int head, string[] param)
|
||||
{
|
||||
return Convert.ToBase64String(
|
||||
Encoding.UTF8.GetBytes(
|
||||
JsonConvert.SerializeObject(new Ctl
|
||||
{ Head = head, Params = param })));
|
||||
}
|
||||
}
|
||||
13
abyssctl/Program.cs
Normal file
13
abyssctl/Program.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
|
||||
|
||||
namespace abyssctl;
|
||||
|
||||
|
||||
static class Program
|
||||
{
|
||||
static async Task<int> Main(string[] args)
|
||||
{
|
||||
var app = new App.App();
|
||||
return await app.RunAsync(args);
|
||||
}
|
||||
}
|
||||
50
abyssctl/Static/SocketExtensions.cs
Normal file
50
abyssctl/Static/SocketExtensions.cs
Normal file
@@ -0,0 +1,50 @@
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
|
||||
namespace abyssctl.Static;
|
||||
|
||||
public static class SocketExtensions
|
||||
{
|
||||
public static async Task<string> ReadBase64Async(this Socket socket, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var buffer = new byte[4096];
|
||||
var sb = new StringBuilder();
|
||||
|
||||
while (true)
|
||||
{
|
||||
int bytesRead = await socket.ReceiveAsync(buffer, SocketFlags.None, cancellationToken).ConfigureAwait(false);
|
||||
if (bytesRead == 0)
|
||||
throw new SocketException((int)SocketError.ConnectionReset);
|
||||
|
||||
string chunk = Encoding.UTF8.GetString(buffer, 0, bytesRead);
|
||||
sb.Append(chunk);
|
||||
|
||||
int newlineIndex = sb.ToString().IndexOf('\n');
|
||||
if (newlineIndex >= 0)
|
||||
{
|
||||
string base64 = sb.ToString(0, newlineIndex).Trim();
|
||||
sb.Remove(0, newlineIndex + 1);
|
||||
return base64;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task WriteBase64Async(this Socket socket, string base64, CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(base64))
|
||||
throw new ArgumentException("Base64 string cannot be null or empty.", nameof(base64));
|
||||
|
||||
string message = base64 + "\n";
|
||||
byte[] data = Encoding.UTF8.GetBytes(message);
|
||||
|
||||
int totalSent = 0;
|
||||
while (totalSent < data.Length)
|
||||
{
|
||||
int sent = await socket.SendAsync(data.AsMemory(totalSent), SocketFlags.None, cancellationToken).ConfigureAwait(false);
|
||||
if (sent == 0)
|
||||
throw new SocketException((int)SocketError.ConnectionReset);
|
||||
|
||||
totalSent += sent;
|
||||
}
|
||||
}
|
||||
}
|
||||
24
abyssctl/abyssctl.csproj
Normal file
24
abyssctl/abyssctl.csproj
Normal file
@@ -0,0 +1,24 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<LangVersion>13</LangVersion>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<PublishAot>false</PublishAot>
|
||||
<InvariantGlobalization>true</InvariantGlobalization>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
|
||||
<OutputPath>../build/</OutputPath>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="CommandLineParser" Version="2.9.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.CommandLine" Version="9.0.9" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
|
||||
<PackageReference Include="System.CommandLine" Version="2.0.0-rc.1.25451.107" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
Reference in New Issue
Block a user