Minor changes
Empty file ISO Add date back for just .kanbn Removed HardcodedFileSearchAndSort Sync with 01-23 JsonToTsv System.Text.Json White-List Ready to move to Move Helper Remove Whitelist Force Start At Check for .git directory before ls Optional Allow root for unc path nuget bump PreVerify EnforceCodeStyleInBuild dotnet_analyzer_diagnostic HelperGit searchDelegate Host File AlertIfNewDeviceIsConnected AOT SetFrontMatterAndH1 Match Error Unknown with better logging Undo 04-05 WriteAppendToHostConfFile MonA IsKanbanIndex Dotnet Format Pre-commit NPM CreateWindowsShortcut Working directory Split description Copy tests Ready to test Delete after a couple of days GitConfigCleanUp knb Files
This commit is contained in:
parent
84ad97ac6e
commit
4e3f06bb44
@ -90,26 +90,48 @@ csharp_style_var_elsewhere = false:warning
|
||||
csharp_style_var_for_built_in_types = false:warning
|
||||
csharp_style_var_when_type_is_apparent = false:warning
|
||||
csharp_using_directive_placement = outside_namespace
|
||||
dotnet_analyzer_diagnostic.category-Design.severity = error
|
||||
dotnet_analyzer_diagnostic.category-Documentation.severity = error
|
||||
dotnet_analyzer_diagnostic.category-Globalization.severity = none
|
||||
dotnet_analyzer_diagnostic.category-Interoperability.severity = error
|
||||
dotnet_analyzer_diagnostic.category-Maintainability.severity = error
|
||||
dotnet_analyzer_diagnostic.category-Naming.severity = none
|
||||
dotnet_analyzer_diagnostic.category-Performance.severity = none
|
||||
dotnet_analyzer_diagnostic.category-Reliability.severity = error
|
||||
dotnet_analyzer_diagnostic.category-Security.severity = error
|
||||
dotnet_analyzer_diagnostic.category-SingleFile.severity = error
|
||||
dotnet_analyzer_diagnostic.category-Style.severity = error
|
||||
dotnet_analyzer_diagnostic.category-Usage.severity = error
|
||||
dotnet_code_quality_unused_parameters = all
|
||||
dotnet_code_quality_unused_parameters = non_public # IDE0060: Remove unused parameter
|
||||
dotnet_code_quality_unused_parameters = non_public
|
||||
dotnet_code_quality.CAXXXX.api_surface = private, internal
|
||||
dotnet_diagnostic.CA1825.severity = warning # CA1823: Avoid zero-length array allocations
|
||||
dotnet_diagnostic.CA1001.severity = error # CA1001: Types that own disposable fields should be disposable
|
||||
dotnet_diagnostic.CA1051.severity = error # CA1051: Do not declare visible instance fields
|
||||
dotnet_diagnostic.CA1511.severity = warning # CA1511: Use 'ArgumentException.ThrowIfNullOrEmpty' instead of explicitly throwing a new exception instance
|
||||
dotnet_diagnostic.CA1513.severity = warning # Use 'ObjectDisposedException.ThrowIf' instead of explicitly throwing a new exception instance
|
||||
dotnet_diagnostic.CA1825.severity = warning # CA1825: Avoid zero-length array allocations
|
||||
dotnet_diagnostic.CA1829.severity = warning # CA1829: Use Length/Count property instead of Count() when available
|
||||
dotnet_diagnostic.CA1834.severity = warning # CA1834: Consider using 'StringBuilder.Append(char)' when applicable
|
||||
dotnet_diagnostic.CA1860.severity = error # CA1860: Prefer comparing 'Count' to 0 rather than using 'Any()', both for clarity and for performance
|
||||
dotnet_diagnostic.CA1862.severity = warning # CA1862: Prefer using 'string.Equals(string, StringComparison)' to perform a case-insensitive comparison, but keep in mind that this might cause subtle changes in behavior, so make sure to conduct thorough testing after applying the suggestion, or if culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase'
|
||||
dotnet_diagnostic.CA1869.severity = none # CA1869: Avoid creating a new 'JsonSerializerOptions' instance for every serialization operation. Cache and reuse instances instead.
|
||||
dotnet_diagnostic.CA2201.severity = none # CA2201: Exception type System.NullReferenceException is reserved by the runtime
|
||||
dotnet_diagnostic.CA2254.severity = none # CA2254: The logging message template should not vary between calls to 'LoggerExtensions.LogInformation(ILogger, string?, params object?[])'
|
||||
dotnet_diagnostic.IDE0001.severity = warning # IDE0001: Simplify name
|
||||
dotnet_diagnostic.IDE0002.severity = warning # Simplify (member access) - System.Version.Equals("1", "2"); Version.Equals("1", "2");
|
||||
dotnet_diagnostic.IDE0004.severity = warning # IDE0004: Cast is redundant.
|
||||
dotnet_diagnostic.IDE0005.severity = warning # Using directive is unnecessary
|
||||
dotnet_diagnostic.IDE0010.severity = none # Add missing cases to switch statement (IDE0010)
|
||||
dotnet_diagnostic.IDE0028.severity = error # IDE0028: Collection initialization can be simplified
|
||||
dotnet_diagnostic.IDE0031.severity = warning # Use null propagation (IDE0031)
|
||||
dotnet_diagnostic.IDE0047.severity = warning # IDE0047: Parentheses can be removed
|
||||
dotnet_diagnostic.IDE0048.severity = none # Parentheses preferences (IDE0047 and IDE0048)
|
||||
dotnet_diagnostic.IDE0049.severity = warning # Use language keywords instead of framework type names for type references (IDE0049)
|
||||
dotnet_diagnostic.IDE0051.severity = error # Private member '' is unused [, ]
|
||||
dotnet_diagnostic.IDE0058.severity = warning # IDE0058: Expression value is never used
|
||||
dotnet_diagnostic.IDE0060.severity = warning # IDE0060: Remove unused parameter
|
||||
dotnet_diagnostic.IDE0060.severity = error # IDE0060: Remove unused parameter
|
||||
dotnet_diagnostic.IDE0074.severity = warning # IDE0074: Use compound assignment
|
||||
dotnet_diagnostic.IDE0130.severity = none # Namespace does not match folder structure (IDE0130)
|
||||
dotnet_diagnostic.IDE0270.severity = warning # IDE0270: Null check can be simplified
|
||||
dotnet_diagnostic.IDE0290.severity = none # Use primary constructor [Distance]csharp(IDE0290)
|
||||
dotnet_diagnostic.IDE0300.severity = error # IDE0300: Collection initialization can be simplified
|
||||
|
6
.gitignore
vendored
6
.gitignore
vendored
@ -330,4 +330,8 @@ ASALocalRun/
|
||||
|
||||
.vscode/Helper/**
|
||||
|
||||
.kanbn
|
||||
.kanbn
|
||||
|
||||
.extensions-vscode
|
||||
.extensions-vscode-oss
|
||||
.extensions-vscode-insiders
|
||||
|
312
.vscode/.json
vendored
Normal file
312
.vscode/.json
vendored
Normal file
@ -0,0 +1,312 @@
|
||||
[
|
||||
{
|
||||
"id": "403675d4-631e-40bb-900e-fae36d9c9cdd",
|
||||
"deviceAssetId": "449501900719.jpg",
|
||||
"ownerId": "fc9fd5a1-d1b3-4080-a21c-daf9b1c24593",
|
||||
"deviceId": "Library Import",
|
||||
"type": "IMAGE",
|
||||
"originalPath": "/var/snap/immich-distribution/pictures/71/449501900719.jpg",
|
||||
"previewPath": "/var/snap/immich-distribution/common/upload/thumbs/fc9fd5a1-d1b3-4080-a21c-daf9b1c24593/40/36/403675d4-631e-40bb-900e-fae36d9c9cdd-preview.jpeg",
|
||||
"fileCreatedAt": "2016-12-02T02:34:23-07:00",
|
||||
"fileModifiedAt": "2016-12-02T02:34:22-07:00",
|
||||
"isFavorite": false,
|
||||
"duration": null,
|
||||
"thumbnailPath": "/var/snap/immich-distribution/common/upload/thumbs/fc9fd5a1-d1b3-4080-a21c-daf9b1c24593/40/36/403675d4-631e-40bb-900e-fae36d9c9cdd-thumbnail.webp",
|
||||
"encodedVideoPath": "",
|
||||
"checksum": "\\x28b46dbf4864b92f18800815cf8145c38d037e92",
|
||||
"isVisible": true,
|
||||
"livePhotoVideoId": null,
|
||||
"updatedAt": "2024-04-25T13:13:20.074314-07:00",
|
||||
"createdAt": "2024-04-25T10:14:24.253144-07:00",
|
||||
"isArchived": false,
|
||||
"originalFileName": "449501900719.jpg",
|
||||
"sidecarPath": null,
|
||||
"isReadOnly": true,
|
||||
"thumbhash": "\\xe5a9090d8257787870788886886877776870760aa9",
|
||||
"isOffline": false,
|
||||
"libraryId": "af11ab7c-0782-4b7a-ba8e-fe68cf9a718d",
|
||||
"isExternal": true,
|
||||
"deletedAt": null,
|
||||
"localDateTime": "2016-12-01T19:34:23-07:00",
|
||||
"stackId": null
|
||||
},
|
||||
{
|
||||
"id": "11ceb05f-8c94-46cd-9a7e-1c06be5a18b8",
|
||||
"deviceAssetId": "015516300831.jpg",
|
||||
"ownerId": "fc9fd5a1-d1b3-4080-a21c-daf9b1c24593",
|
||||
"deviceId": "Library Import",
|
||||
"type": "IMAGE",
|
||||
"originalPath": "/var/snap/immich-distribution/pictures/83/015516300831.jpg",
|
||||
"previewPath": "/var/snap/immich-distribution/common/upload/thumbs/fc9fd5a1-d1b3-4080-a21c-daf9b1c24593/11/ce/11ceb05f-8c94-46cd-9a7e-1c06be5a18b8-preview.jpeg",
|
||||
"fileCreatedAt": "2014-05-03T14:44:20-07:00",
|
||||
"fileModifiedAt": "2014-11-17T11:18:58-07:00",
|
||||
"isFavorite": false,
|
||||
"duration": null,
|
||||
"thumbnailPath": "/var/snap/immich-distribution/common/upload/thumbs/fc9fd5a1-d1b3-4080-a21c-daf9b1c24593/11/ce/11ceb05f-8c94-46cd-9a7e-1c06be5a18b8-thumbnail.webp",
|
||||
"encodedVideoPath": "",
|
||||
"checksum": "\\x5b976715bab319b3bdc69d5f337701a062494e0b",
|
||||
"isVisible": true,
|
||||
"livePhotoVideoId": null,
|
||||
"updatedAt": "2024-04-25T13:07:55.048725-07:00",
|
||||
"createdAt": "2024-04-25T10:14:12.923101-07:00",
|
||||
"isArchived": false,
|
||||
"originalFileName": "015516300831.jpg",
|
||||
"sidecarPath": null,
|
||||
"isReadOnly": true,
|
||||
"thumbhash": "\\x5a08120c00771777f87778979877597fbef365",
|
||||
"isOffline": false,
|
||||
"libraryId": "af11ab7c-0782-4b7a-ba8e-fe68cf9a718d",
|
||||
"isExternal": true,
|
||||
"deletedAt": null,
|
||||
"localDateTime": "2014-05-03T14:44:20-07:00",
|
||||
"stackId": null
|
||||
},
|
||||
{
|
||||
"id": "e8e94a75-2b0c-48f6-b26a-76f5cbe46233",
|
||||
"deviceAssetId": "985177500821.jpg",
|
||||
"ownerId": "fc9fd5a1-d1b3-4080-a21c-daf9b1c24593",
|
||||
"deviceId": "Library Import",
|
||||
"type": "IMAGE",
|
||||
"originalPath": "/var/snap/immich-distribution/pictures/82/985177500821.jpg",
|
||||
"previewPath": "/var/snap/immich-distribution/common/upload/thumbs/fc9fd5a1-d1b3-4080-a21c-daf9b1c24593/e8/e9/e8e94a75-2b0c-48f6-b26a-76f5cbe46233-preview.jpeg",
|
||||
"fileCreatedAt": "2004-04-28T20:31:40-07:00",
|
||||
"fileModifiedAt": "2018-05-16T21:41:26.093-07:00",
|
||||
"isFavorite": false,
|
||||
"duration": null,
|
||||
"thumbnailPath": "/var/snap/immich-distribution/common/upload/thumbs/fc9fd5a1-d1b3-4080-a21c-daf9b1c24593/e8/e9/e8e94a75-2b0c-48f6-b26a-76f5cbe46233-thumbnail.webp",
|
||||
"encodedVideoPath": "",
|
||||
"checksum": "\\x176b222fa88bc72aaf81031f3b7f73644b178de4",
|
||||
"isVisible": true,
|
||||
"livePhotoVideoId": null,
|
||||
"updatedAt": "2024-04-25T13:07:55.667409-07:00",
|
||||
"createdAt": "2024-04-25T10:14:12.945414-07:00",
|
||||
"isArchived": false,
|
||||
"originalFileName": "985177500821.jpg",
|
||||
"sidecarPath": null,
|
||||
"isReadOnly": true,
|
||||
"thumbhash": "\\xdf07121d0687868f87378788887877887780670789",
|
||||
"isOffline": false,
|
||||
"libraryId": "af11ab7c-0782-4b7a-ba8e-fe68cf9a718d",
|
||||
"isExternal": true,
|
||||
"deletedAt": null,
|
||||
"localDateTime": "2004-04-28T20:31:40-07:00",
|
||||
"stackId": null
|
||||
},
|
||||
{
|
||||
"id": "4091bebd-4c26-4d30-bd3a-f2160a54b451",
|
||||
"deviceAssetId": "956694610829.jpg",
|
||||
"ownerId": "fc9fd5a1-d1b3-4080-a21c-daf9b1c24593",
|
||||
"deviceId": "Library Import",
|
||||
"type": "IMAGE",
|
||||
"originalPath": "/var/snap/immich-distribution/pictures/82/956694610829.jpg",
|
||||
"previewPath": "/var/snap/immich-distribution/common/upload/thumbs/fc9fd5a1-d1b3-4080-a21c-daf9b1c24593/40/91/4091bebd-4c26-4d30-bd3a-f2160a54b451-preview.jpeg",
|
||||
"fileCreatedAt": "2010-07-05T09:10:13.2-07:00",
|
||||
"fileModifiedAt": "2010-07-05T08:10:12-07:00",
|
||||
"isFavorite": false,
|
||||
"duration": null,
|
||||
"thumbnailPath": "/var/snap/immich-distribution/common/upload/thumbs/fc9fd5a1-d1b3-4080-a21c-daf9b1c24593/40/91/4091bebd-4c26-4d30-bd3a-f2160a54b451-thumbnail.webp",
|
||||
"encodedVideoPath": "",
|
||||
"checksum": "\\xc2eb5667d6da5ead1be71c51064ea293ad413ea6",
|
||||
"isVisible": true,
|
||||
"livePhotoVideoId": null,
|
||||
"updatedAt": "2024-04-25T13:07:56.364375-07:00",
|
||||
"createdAt": "2024-04-25T10:14:12.976197-07:00",
|
||||
"isArchived": false,
|
||||
"originalFileName": "956694610829.jpg",
|
||||
"sidecarPath": null,
|
||||
"isReadOnly": true,
|
||||
"thumbhash": "\\x12080a0d82668886808887867877877867807906b7",
|
||||
"isOffline": false,
|
||||
"libraryId": "af11ab7c-0782-4b7a-ba8e-fe68cf9a718d",
|
||||
"isExternal": true,
|
||||
"deletedAt": null,
|
||||
"localDateTime": "2010-07-05T09:10:13.2-07:00",
|
||||
"stackId": null
|
||||
},
|
||||
{
|
||||
"id": "c7bf1944-9f71-4808-8ff9-b0f972e907b0",
|
||||
"deviceAssetId": "948800300821.jpg",
|
||||
"ownerId": "fc9fd5a1-d1b3-4080-a21c-daf9b1c24593",
|
||||
"deviceId": "Library Import",
|
||||
"type": "IMAGE",
|
||||
"originalPath": "/var/snap/immich-distribution/pictures/82/948800300821.jpg",
|
||||
"previewPath": "/var/snap/immich-distribution/common/upload/thumbs/fc9fd5a1-d1b3-4080-a21c-daf9b1c24593/c7/bf/c7bf1944-9f71-4808-8ff9-b0f972e907b0-preview.jpeg",
|
||||
"fileCreatedAt": "2009-10-09T05:35:00.2-07:00",
|
||||
"fileModifiedAt": "2009-10-09T04:35:00-07:00",
|
||||
"isFavorite": false,
|
||||
"duration": null,
|
||||
"thumbnailPath": "/var/snap/immich-distribution/common/upload/thumbs/fc9fd5a1-d1b3-4080-a21c-daf9b1c24593/c7/bf/c7bf1944-9f71-4808-8ff9-b0f972e907b0-thumbnail.webp",
|
||||
"encodedVideoPath": "",
|
||||
"checksum": "\\x3c5c87ab7e442d1f7a0f2a12678c1d6be00dbc7b",
|
||||
"isVisible": true,
|
||||
"livePhotoVideoId": null,
|
||||
"updatedAt": "2024-04-25T13:07:56.553262-07:00",
|
||||
"createdAt": "2024-04-25T10:14:12.982686-07:00",
|
||||
"isArchived": false,
|
||||
"originalFileName": "948800300821.jpg",
|
||||
"sidecarPath": null,
|
||||
"isReadOnly": true,
|
||||
"thumbhash": "\\x103806258e02bd47937779a478997768fd3bcb9fa4",
|
||||
"isOffline": false,
|
||||
"libraryId": "af11ab7c-0782-4b7a-ba8e-fe68cf9a718d",
|
||||
"isExternal": true,
|
||||
"deletedAt": null,
|
||||
"localDateTime": "2009-10-09T05:35:00.2-07:00",
|
||||
"stackId": null
|
||||
},
|
||||
{
|
||||
"id": "4f5ea703-47e9-48c6-9366-0cc10630dac2",
|
||||
"deviceAssetId": "898525300821.jpg",
|
||||
"ownerId": "fc9fd5a1-d1b3-4080-a21c-daf9b1c24593",
|
||||
"deviceId": "Library Import",
|
||||
"type": "IMAGE",
|
||||
"originalPath": "/var/snap/immich-distribution/pictures/82/898525300821.jpg",
|
||||
"previewPath": "/var/snap/immich-distribution/common/upload/thumbs/fc9fd5a1-d1b3-4080-a21c-daf9b1c24593/4f/5e/4f5ea703-47e9-48c6-9366-0cc10630dac2-preview.jpeg",
|
||||
"fileCreatedAt": "2020-12-25T08:35:04.92-07:00",
|
||||
"fileModifiedAt": "2020-12-25T08:35:04-07:00",
|
||||
"isFavorite": false,
|
||||
"duration": null,
|
||||
"thumbnailPath": "/var/snap/immich-distribution/common/upload/thumbs/fc9fd5a1-d1b3-4080-a21c-daf9b1c24593/4f/5e/4f5ea703-47e9-48c6-9366-0cc10630dac2-thumbnail.webp",
|
||||
"encodedVideoPath": "",
|
||||
"checksum": "\\xf706263e450c9a26feaeba2dd14fe0fd8f22e623",
|
||||
"isVisible": true,
|
||||
"livePhotoVideoId": null,
|
||||
"updatedAt": "2024-04-25T13:07:58.530848-07:00",
|
||||
"createdAt": "2024-04-25T10:14:13.048275-07:00",
|
||||
"isArchived": false,
|
||||
"originalFileName": "898525300821.jpg",
|
||||
"sidecarPath": null,
|
||||
"isReadOnly": true,
|
||||
"thumbhash": "\\x5518060d8208976849959a99687678687f8dae48f6",
|
||||
"isOffline": false,
|
||||
"libraryId": "af11ab7c-0782-4b7a-ba8e-fe68cf9a718d",
|
||||
"isExternal": true,
|
||||
"deletedAt": null,
|
||||
"localDateTime": "2020-12-25T01:35:04.92-07:00",
|
||||
"stackId": null
|
||||
},
|
||||
{
|
||||
"id": "86c813ad-2a1c-489f-8fc2-0b76a21889c0",
|
||||
"deviceAssetId": "864710800829.jpg",
|
||||
"ownerId": "fc9fd5a1-d1b3-4080-a21c-daf9b1c24593",
|
||||
"deviceId": "Library Import",
|
||||
"type": "IMAGE",
|
||||
"originalPath": "/var/snap/immich-distribution/pictures/82/864710800829.jpg",
|
||||
"previewPath": "/var/snap/immich-distribution/common/upload/thumbs/fc9fd5a1-d1b3-4080-a21c-daf9b1c24593/86/c8/86c813ad-2a1c-489f-8fc2-0b76a21889c0-preview.jpeg",
|
||||
"fileCreatedAt": "2004-04-28T20:00:46-07:00",
|
||||
"fileModifiedAt": "2004-04-28T19:00:46-07:00",
|
||||
"isFavorite": false,
|
||||
"duration": null,
|
||||
"thumbnailPath": "/var/snap/immich-distribution/common/upload/thumbs/fc9fd5a1-d1b3-4080-a21c-daf9b1c24593/86/c8/86c813ad-2a1c-489f-8fc2-0b76a21889c0-thumbnail.webp",
|
||||
"encodedVideoPath": "",
|
||||
"checksum": "\\x9061edbf75f11526cef2c832ba339267509eaec4",
|
||||
"isVisible": true,
|
||||
"livePhotoVideoId": null,
|
||||
"updatedAt": "2024-04-25T13:07:59.171233-07:00",
|
||||
"createdAt": "2024-04-25T10:14:13.078169-07:00",
|
||||
"isArchived": false,
|
||||
"originalFileName": "864710800829.jpg",
|
||||
"sidecarPath": null,
|
||||
"isReadOnly": true,
|
||||
"thumbhash": "\\x140812250674874f87777669788778887a93a0470a",
|
||||
"isOffline": false,
|
||||
"libraryId": "af11ab7c-0782-4b7a-ba8e-fe68cf9a718d",
|
||||
"isExternal": true,
|
||||
"deletedAt": null,
|
||||
"localDateTime": "2004-04-28T20:00:46-07:00",
|
||||
"stackId": null
|
||||
},
|
||||
{
|
||||
"id": "b65121d8-4a74-4f27-9d6f-c582ffc444dc",
|
||||
"deviceAssetId": "862274900829.jpg",
|
||||
"ownerId": "fc9fd5a1-d1b3-4080-a21c-daf9b1c24593",
|
||||
"deviceId": "Library Import",
|
||||
"type": "IMAGE",
|
||||
"originalPath": "/var/snap/immich-distribution/pictures/82/862274900829.jpg",
|
||||
"previewPath": "/var/snap/immich-distribution/common/upload/thumbs/fc9fd5a1-d1b3-4080-a21c-daf9b1c24593/b6/51/b65121d8-4a74-4f27-9d6f-c582ffc444dc-preview.jpeg",
|
||||
"fileCreatedAt": "2018-08-17T22:50:55.15-07:00",
|
||||
"fileModifiedAt": "2022-11-03T20:25:09.161-07:00",
|
||||
"isFavorite": false,
|
||||
"duration": null,
|
||||
"thumbnailPath": "/var/snap/immich-distribution/common/upload/thumbs/fc9fd5a1-d1b3-4080-a21c-daf9b1c24593/b6/51/b65121d8-4a74-4f27-9d6f-c582ffc444dc-thumbnail.webp",
|
||||
"encodedVideoPath": "",
|
||||
"checksum": "\\xd4f623e97acd727868fe0e191c170e449d4456a5",
|
||||
"isVisible": true,
|
||||
"livePhotoVideoId": null,
|
||||
"updatedAt": "2024-04-25T13:07:59.640678-07:00",
|
||||
"createdAt": "2024-04-25T10:14:13.087927-07:00",
|
||||
"isArchived": false,
|
||||
"originalFileName": "862274900829.jpg",
|
||||
"sidecarPath": null,
|
||||
"isReadOnly": true,
|
||||
"thumbhash": "\\x99180a0d045977a077687887777678876a806b0867",
|
||||
"isOffline": false,
|
||||
"libraryId": "af11ab7c-0782-4b7a-ba8e-fe68cf9a718d",
|
||||
"isExternal": true,
|
||||
"deletedAt": null,
|
||||
"localDateTime": "2018-08-17T15:50:55.15-07:00",
|
||||
"stackId": null
|
||||
},
|
||||
{
|
||||
"id": "09fa281c-b828-47f6-8fbb-a5856edb63b5",
|
||||
"deviceAssetId": "840656100829.jpg",
|
||||
"ownerId": "fc9fd5a1-d1b3-4080-a21c-daf9b1c24593",
|
||||
"deviceId": "Library Import",
|
||||
"type": "IMAGE",
|
||||
"originalPath": "/var/snap/immich-distribution/pictures/82/840656100829.jpg",
|
||||
"previewPath": "/var/snap/immich-distribution/common/upload/thumbs/fc9fd5a1-d1b3-4080-a21c-daf9b1c24593/09/fa/09fa281c-b828-47f6-8fbb-a5856edb63b5-preview.jpeg",
|
||||
"fileCreatedAt": "2019-05-30T14:56:36.82-07:00",
|
||||
"fileModifiedAt": "2019-05-30T14:56:36-07:00",
|
||||
"isFavorite": false,
|
||||
"duration": null,
|
||||
"thumbnailPath": "/var/snap/immich-distribution/common/upload/thumbs/fc9fd5a1-d1b3-4080-a21c-daf9b1c24593/09/fa/09fa281c-b828-47f6-8fbb-a5856edb63b5-thumbnail.webp",
|
||||
"encodedVideoPath": "",
|
||||
"checksum": "\\xd215606441cefcc295130262bad9fed96d9ac40e",
|
||||
"isVisible": true,
|
||||
"livePhotoVideoId": null,
|
||||
"updatedAt": "2024-04-25T13:08:00.211274-07:00",
|
||||
"createdAt": "2024-04-25T10:14:13.104556-07:00",
|
||||
"isArchived": false,
|
||||
"originalFileName": "840656100829.jpg",
|
||||
"sidecarPath": null,
|
||||
"isReadOnly": true,
|
||||
"thumbhash": "\\xd6070a0d826f62873c788799993a7777137f679058",
|
||||
"isOffline": false,
|
||||
"libraryId": "af11ab7c-0782-4b7a-ba8e-fe68cf9a718d",
|
||||
"isExternal": true,
|
||||
"deletedAt": null,
|
||||
"localDateTime": "2019-05-30T07:56:36.82-07:00",
|
||||
"stackId": null
|
||||
},
|
||||
{
|
||||
"id": "8c239624-2bea-479d-b7fa-9f2cd5ebc9b7",
|
||||
"deviceAssetId": "812813100821.jpg",
|
||||
"ownerId": "fc9fd5a1-d1b3-4080-a21c-daf9b1c24593",
|
||||
"deviceId": "Library Import",
|
||||
"type": "IMAGE",
|
||||
"originalPath": "/var/snap/immich-distribution/pictures/82/812813100821.jpg",
|
||||
"previewPath": "/var/snap/immich-distribution/common/upload/thumbs/fc9fd5a1-d1b3-4080-a21c-daf9b1c24593/8c/23/8c239624-2bea-479d-b7fa-9f2cd5ebc9b7-preview.jpeg",
|
||||
"fileCreatedAt": "2021-08-28T16:29:07.65-07:00",
|
||||
"fileModifiedAt": "2021-08-28T16:29:08-07:00",
|
||||
"isFavorite": false,
|
||||
"duration": null,
|
||||
"thumbnailPath": "/var/snap/immich-distribution/common/upload/thumbs/fc9fd5a1-d1b3-4080-a21c-daf9b1c24593/8c/23/8c239624-2bea-479d-b7fa-9f2cd5ebc9b7-thumbnail.webp",
|
||||
"encodedVideoPath": "",
|
||||
"checksum": "\\x25a9ffe84298f0e3e7151aaf2eb339908574c035",
|
||||
"isVisible": true,
|
||||
"livePhotoVideoId": null,
|
||||
"updatedAt": "2024-04-25T13:08:00.918411-07:00",
|
||||
"createdAt": "2024-04-25T10:14:13.134038-07:00",
|
||||
"isArchived": false,
|
||||
"originalFileName": "812813100821.jpg",
|
||||
"sidecarPath": null,
|
||||
"isReadOnly": true,
|
||||
"thumbhash": "\\x21080e0d825878767f9678bf7747799612c3b0308a",
|
||||
"isOffline": false,
|
||||
"libraryId": "af11ab7c-0782-4b7a-ba8e-fe68cf9a718d",
|
||||
"isExternal": true,
|
||||
"deletedAt": null,
|
||||
"localDateTime": "2021-08-28T09:29:07.65-07:00",
|
||||
"stackId": null
|
||||
}
|
||||
]
|
7
.vscode/launch.json
vendored
7
.vscode/launch.json
vendored
@ -12,10 +12,9 @@
|
||||
"program": "${workspaceFolder}/bin/Debug/net8.0/win-x64/File-Folder-Helper.dll",
|
||||
"args": [
|
||||
"s",
|
||||
"X",
|
||||
"Day/2024-Q1",
|
||||
"Day-Helper-2024-01-08"
|
||||
],
|
||||
"K",
|
||||
".kanbn"
|
||||
],
|
||||
"cwd": "${workspaceFolder}",
|
||||
"console": "integratedTerminal",
|
||||
"stopAtEntry": false
|
||||
|
8
.vscode/mklink.md
vendored
8
.vscode/mklink.md
vendored
@ -7,9 +7,15 @@ updated: "2023-10-20T04:00:37.259Z"
|
||||
# mklink
|
||||
|
||||
```bash
|
||||
mklink /J "L:\DevOps\Mesa_FI\File-Folder-Helper\.kanbn" "D:\Documents\Kanban\File-Folder-Helper"
|
||||
mklink /J "L:\DevOps\Mesa_FI\File-Folder-Helper\.kanbn" "D:\5-Other-Small\Kanban\File-Folder-Helper"
|
||||
```
|
||||
|
||||
```bash
|
||||
mklink /J "L:\DevOps\Mesa_FI\File-Folder-Helper\.kanbn" "D:\5-Other-Small\Kanban\File-Folder-Helper"
|
||||
```
|
||||
|
||||
```bash
|
||||
mklink /J "L:\DevOps\Mesa_FI\File-Folder-Helper\.extensions-vscode" "C:\Users\phares\.vscode\extensions\ifx.type-script-helper-1.5.2"
|
||||
mklink /J "L:\DevOps\Mesa_FI\File-Folder-Helper\.extensions-vscode-oss" "C:\Users\phares\.vscode-oss\extensions\ifx.type-script-helper-1.5.2"
|
||||
mklink /J "L:\DevOps\Mesa_FI\File-Folder-Helper\.extensions-vscode-insiders" "C:\Users\phares\.vscode-insiders\extensions\ifx.type-script-helper-1.5.2"
|
||||
```
|
||||
|
32
.vscode/pre-commit
vendored
Normal file
32
.vscode/pre-commit
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
#!/bin/sh
|
||||
|
||||
echo "*****eclint fix******"
|
||||
|
||||
before=$(git ls-files --others --modified --deleted --exclude-standard | wc -l)
|
||||
echo "before: $before"
|
||||
|
||||
dotnet format whitespace
|
||||
|
||||
err=$?
|
||||
|
||||
case $err in
|
||||
0) echo success ;;
|
||||
1) echo fail ;;
|
||||
2) echo "unexpected failure" ;;
|
||||
*) echo "I never thought this would happen" ;;
|
||||
esac
|
||||
|
||||
if [ $err -ne 0 ]; then
|
||||
exit $err
|
||||
fi
|
||||
|
||||
after=$(git ls-files --others --modified --deleted --exclude-standard | wc -l)
|
||||
echo "after: $after"
|
||||
|
||||
if [ $after -gt $before ]; then
|
||||
files=$(git ls-files --others --modified --deleted --exclude-standard)
|
||||
echo "Files not formatted correctly: $files"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
exit $err
|
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@ -19,16 +19,19 @@
|
||||
"FAMS",
|
||||
"GIVN",
|
||||
"HUSB",
|
||||
"Immich",
|
||||
"INDI",
|
||||
"Infineon",
|
||||
"Kanban",
|
||||
"kanbn",
|
||||
"Kofax",
|
||||
"NpgSql",
|
||||
"NSFX",
|
||||
"OBJE",
|
||||
"onenote",
|
||||
"pged",
|
||||
"Phares",
|
||||
"Rijndael",
|
||||
"Serilog",
|
||||
"SUBM",
|
||||
"SURN",
|
||||
|
20
.vscode/tasks.json
vendored
20
.vscode/tasks.json
vendored
@ -22,8 +22,8 @@
|
||||
"-p",
|
||||
"${workspaceFolder}/File-Folder-Helper.csproj",
|
||||
"set",
|
||||
"asdf",
|
||||
"123"
|
||||
"_UserSecretsId",
|
||||
"0c43f9aa-96e9-4298-967c-ed069d79e262"
|
||||
],
|
||||
"problemMatcher": "$msCompile"
|
||||
},
|
||||
@ -42,6 +42,16 @@
|
||||
],
|
||||
"problemMatcher": "$msCompile"
|
||||
},
|
||||
{
|
||||
"label": "Format-Whitespaces",
|
||||
"command": "dotnet",
|
||||
"type": "process",
|
||||
"args": [
|
||||
"format",
|
||||
"whitespace"
|
||||
],
|
||||
"problemMatcher": "$msCompile"
|
||||
},
|
||||
{
|
||||
"label": "build",
|
||||
"command": "dotnet",
|
||||
@ -89,8 +99,6 @@
|
||||
"-c",
|
||||
"Release",
|
||||
"-p:PublishAot=true",
|
||||
"--source",
|
||||
"https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet7/nuget/v3/index.json",
|
||||
"${workspaceFolder}/File-Folder-Helper.csproj",
|
||||
"/property:GenerateFullPaths=true",
|
||||
"/consoleloggerparameters:NoSummary"
|
||||
@ -112,7 +120,7 @@
|
||||
{
|
||||
"label": "File-Folder-Helper AOT s M Self .Kanbn Tasks",
|
||||
"type": "shell",
|
||||
"command": "L:/DevOps/Mesa_FI/File-Folder-Helper/bin/Release/net8.0/win-x64/publish/File-Folder-Helper.exe s M '.kanbn/tasks'",
|
||||
"command": "L:/DevOps/Mesa_FI/File-Folder-Helper/bin/Release/net8.0/win-x64/publish/File-Folder-Helper.exe s M L:/DevOps/Mesa_FI/File-Folder-Helper L:/DevOps/Mesa_FI/File-Folder-Helper/.kanbn/tasks",
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
@ -124,7 +132,7 @@
|
||||
{
|
||||
"label": "File-Folder-Helper AOT s X SortCodeMethods",
|
||||
"type": "shell",
|
||||
"command": "L:/DevOps/Mesa_FI/File-Folder-Helper/bin/Release/net8.0/win-x64/publish/File-Folder-Helper.exe s X Day/2024-Q1 Day-Helper-2024-01-08",
|
||||
"command": "L:/DevOps/Mesa_FI/File-Folder-Helper/bin/Release/net8.0/win-x64/publish/File-Folder-Helper.exe s X L:/DevOps/Mesa_FI/File-Folder-Helper Day-Helper-2024-01-08 L:/DevOps/Mesa_FI/File-Folder-Helper/Day/2024-Q2",
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
|
@ -1,538 +0,0 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace File_Folder_Helper.Day;
|
||||
|
||||
internal static partial class Helper20231212
|
||||
{
|
||||
|
||||
private record Debugging(
|
||||
[property: JsonPropertyName("Level")] int Level
|
||||
);
|
||||
|
||||
[JsonSourceGenerationOptions(WriteIndented = true, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
[JsonSerializable(typeof(Debugging))]
|
||||
private partial class DebuggingSourceGenerationContext : JsonSerializerContext
|
||||
{
|
||||
}
|
||||
|
||||
private record Distance(
|
||||
[property: JsonPropertyName("Value")] int Value
|
||||
);
|
||||
|
||||
[JsonSourceGenerationOptions(WriteIndented = true, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
[JsonSerializable(typeof(Distance))]
|
||||
private partial class DistanceSourceGenerationContext : JsonSerializerContext
|
||||
{
|
||||
}
|
||||
|
||||
private record Finished(
|
||||
[property: JsonPropertyName("Elapsed")] double Elapsed,
|
||||
[property: JsonPropertyName("Exit")] string Exit,
|
||||
[property: JsonPropertyName("Summary")] string Summary,
|
||||
[property: JsonPropertyName("Time")] int Time,
|
||||
[property: JsonPropertyName("TimeStr")] string TimeStr
|
||||
);
|
||||
|
||||
[JsonSourceGenerationOptions(WriteIndented = true, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
[JsonSerializable(typeof(Finished))]
|
||||
private partial class FinishedSourceGenerationContext : JsonSerializerContext
|
||||
{
|
||||
}
|
||||
|
||||
private record Hop(
|
||||
[property: JsonPropertyName("Host")] string Host,
|
||||
[property: JsonPropertyName("IPAddr")] string IPAddr,
|
||||
[property: JsonPropertyName("RTT")] double RTT,
|
||||
[property: JsonPropertyName("TTL")] int TTL
|
||||
);
|
||||
|
||||
[JsonSourceGenerationOptions(WriteIndented = true, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
[JsonSerializable(typeof(Hop))]
|
||||
private partial class HopSourceGenerationContext : JsonSerializerContext
|
||||
{
|
||||
}
|
||||
|
||||
private record Host(
|
||||
[property: JsonPropertyName("Distance")] Distance Distance,
|
||||
[property: JsonPropertyName("EndTime")] int EndTime,
|
||||
[property: JsonPropertyName("HostAddress")] IReadOnlyList<HostAddress> HostAddresses,
|
||||
[property: JsonPropertyName("HostNames")] HostNames HostNames,
|
||||
[property: JsonPropertyName("IPIDSequence")] IPIDSequence IPIDSequence,
|
||||
[property: JsonPropertyName("OS")] OS OS,
|
||||
[property: JsonPropertyName("Port")] IReadOnlyList<Port> Ports,
|
||||
[property: JsonPropertyName("StartTime")] int StartTime,
|
||||
[property: JsonPropertyName("Status")] Status Status,
|
||||
[property: JsonPropertyName("TCPSequence")] TCPSequence TCPSequence,
|
||||
[property: JsonPropertyName("TCPTSSequence")] TCPTSSequence TCPTSSequence,
|
||||
[property: JsonPropertyName("Trace")] Trace Trace,
|
||||
[property: JsonPropertyName("Uptime")] Uptime Uptime
|
||||
);
|
||||
|
||||
[JsonSourceGenerationOptions(WriteIndented = true, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
[JsonSerializable(typeof(Host))]
|
||||
private partial class HostSourceGenerationContext : JsonSerializerContext
|
||||
{
|
||||
}
|
||||
|
||||
private record HostAddress(
|
||||
[property: JsonPropertyName("Address")] string Address,
|
||||
[property: JsonPropertyName("AddressType")] string AddressType,
|
||||
[property: JsonPropertyName("Vendor")] string Vendor
|
||||
);
|
||||
|
||||
[JsonSourceGenerationOptions(WriteIndented = true, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
[JsonSerializable(typeof(HostAddress))]
|
||||
private partial class HostAddressSourceGenerationContext : JsonSerializerContext
|
||||
{
|
||||
}
|
||||
|
||||
private record HostName(
|
||||
[property: JsonPropertyName("Name")] string Name,
|
||||
[property: JsonPropertyName("Type")] string Type
|
||||
);
|
||||
|
||||
[JsonSourceGenerationOptions(WriteIndented = true, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
[JsonSerializable(typeof(HostName))]
|
||||
private partial class HostNameSourceGenerationContext : JsonSerializerContext
|
||||
{
|
||||
}
|
||||
|
||||
private record HostNames(
|
||||
[property: JsonPropertyName("HostName")] IReadOnlyList<HostName> HostName
|
||||
);
|
||||
|
||||
[JsonSourceGenerationOptions(WriteIndented = true, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
[JsonSerializable(typeof(HostNames))]
|
||||
private partial class HostNamesSourceGenerationContext : JsonSerializerContext
|
||||
{
|
||||
}
|
||||
|
||||
private record Hosts(
|
||||
[property: JsonPropertyName("Down")] int Down,
|
||||
[property: JsonPropertyName("Total")] int Total,
|
||||
[property: JsonPropertyName("Up")] int Up
|
||||
);
|
||||
|
||||
[JsonSourceGenerationOptions(WriteIndented = true, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
[JsonSerializable(typeof(Hosts))]
|
||||
private partial class HostsSourceGenerationContext : JsonSerializerContext
|
||||
{
|
||||
}
|
||||
|
||||
private record IPIDSequence(
|
||||
[property: JsonPropertyName("Class")] string Class,
|
||||
[property: JsonPropertyName("Values")] string Values
|
||||
);
|
||||
|
||||
[JsonSourceGenerationOptions(WriteIndented = true, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
[JsonSerializable(typeof(IPIDSequence))]
|
||||
private partial class IPIDSequenceSourceGenerationContext : JsonSerializerContext
|
||||
{
|
||||
}
|
||||
|
||||
private record OS(
|
||||
[property: JsonPropertyName("OSClass")] object OSClass,
|
||||
[property: JsonPropertyName("OSMatch")] IReadOnlyList<OSMatch> OSMatches,
|
||||
[property: JsonPropertyName("OSPortUsed")] IReadOnlyList<OSPortUsed> OSPortsUsed
|
||||
);
|
||||
|
||||
[JsonSourceGenerationOptions(WriteIndented = true, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
[JsonSerializable(typeof(OS))]
|
||||
private partial class OSSourceGenerationContext : JsonSerializerContext
|
||||
{
|
||||
}
|
||||
|
||||
private record OSMatch(
|
||||
[property: JsonPropertyName("Accuracy")] string Accuracy,
|
||||
[property: JsonPropertyName("Line")] string Line,
|
||||
[property: JsonPropertyName("Name")] string Name
|
||||
);
|
||||
|
||||
[JsonSourceGenerationOptions(WriteIndented = true, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
[JsonSerializable(typeof(OSMatch))]
|
||||
private partial class OSMatchSourceGenerationContext : JsonSerializerContext
|
||||
{
|
||||
}
|
||||
|
||||
private record OSPortUsed(
|
||||
[property: JsonPropertyName("PortID")] int PortID,
|
||||
[property: JsonPropertyName("Protocol")] string Protocol,
|
||||
[property: JsonPropertyName("State")] string State
|
||||
);
|
||||
|
||||
[JsonSourceGenerationOptions(WriteIndented = true, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
[JsonSerializable(typeof(OSPortUsed))]
|
||||
private partial class OSPortUsedSourceGenerationContext : JsonSerializerContext
|
||||
{
|
||||
}
|
||||
|
||||
private record Port(
|
||||
[property: JsonPropertyName("PortID")] int PortID,
|
||||
[property: JsonPropertyName("Protocol")] string Protocol,
|
||||
[property: JsonPropertyName("Script")] IReadOnlyList<Script> Scripts,
|
||||
[property: JsonPropertyName("Service")] Service Service,
|
||||
[property: JsonPropertyName("State")] State State
|
||||
);
|
||||
|
||||
[JsonSourceGenerationOptions(WriteIndented = true, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
[JsonSerializable(typeof(Port))]
|
||||
private partial class PortSourceGenerationContext : JsonSerializerContext
|
||||
{
|
||||
}
|
||||
|
||||
private record Record(
|
||||
[property: JsonPropertyName("Args")] string Args,
|
||||
[property: JsonPropertyName("Debugging")] Debugging Debugging,
|
||||
[property: JsonPropertyName("Host")] List<Host> Hosts,
|
||||
[property: JsonPropertyName("RunStats")] RunStats RunStats,
|
||||
[property: JsonPropertyName("ScanInfo")] ScanInfo ScanInfo,
|
||||
[property: JsonPropertyName("Scanner")] string Scanner,
|
||||
[property: JsonPropertyName("Start")] int Start,
|
||||
[property: JsonPropertyName("StartStr")] string StartStr,
|
||||
[property: JsonPropertyName("Verbose")] Verbose Verbose,
|
||||
[property: JsonPropertyName("Version")] string Version
|
||||
);
|
||||
|
||||
[JsonSourceGenerationOptions(WriteIndented = true, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
[JsonSerializable(typeof(Record))]
|
||||
private partial class RecordSourceGenerationContext : JsonSerializerContext
|
||||
{
|
||||
}
|
||||
|
||||
private record RunStats(
|
||||
[property: JsonPropertyName("Finished")] Finished Finished,
|
||||
[property: JsonPropertyName("Hosts")] Hosts Hosts
|
||||
);
|
||||
|
||||
[JsonSourceGenerationOptions(WriteIndented = true, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
[JsonSerializable(typeof(RunStats))]
|
||||
private partial class RunStatsSourceGenerationContext : JsonSerializerContext
|
||||
{
|
||||
}
|
||||
|
||||
private record ScanInfo(
|
||||
[property: JsonPropertyName("NumServices")] int NumServices,
|
||||
[property: JsonPropertyName("Protocol")] string Protocol,
|
||||
[property: JsonPropertyName("Services")] string Services,
|
||||
[property: JsonPropertyName("Type")] string Type
|
||||
);
|
||||
|
||||
[JsonSourceGenerationOptions(WriteIndented = true, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
[JsonSerializable(typeof(ScanInfo))]
|
||||
private partial class ScanInfoSourceGenerationContext : JsonSerializerContext
|
||||
{
|
||||
}
|
||||
|
||||
private record Script(
|
||||
[property: JsonPropertyName("ID")] string ID,
|
||||
[property: JsonPropertyName("Output")] string Output
|
||||
);
|
||||
|
||||
[JsonSourceGenerationOptions(WriteIndented = true, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
[JsonSerializable(typeof(Script))]
|
||||
private partial class ScriptSourceGenerationContext : JsonSerializerContext
|
||||
{
|
||||
}
|
||||
|
||||
private record Service(
|
||||
[property: JsonPropertyName("Conf")] string Conf,
|
||||
[property: JsonPropertyName("CPE")] IReadOnlyList<string> CPEs,
|
||||
[property: JsonPropertyName("ExtraInfo")] string ExtraInfo,
|
||||
[property: JsonPropertyName("Method")] string Method,
|
||||
[property: JsonPropertyName("Name")] string Name,
|
||||
[property: JsonPropertyName("Product")] string Product,
|
||||
[property: JsonPropertyName("Version")] string Version
|
||||
);
|
||||
|
||||
[JsonSourceGenerationOptions(WriteIndented = true, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
[JsonSerializable(typeof(Service))]
|
||||
private partial class ServiceSourceGenerationContext : JsonSerializerContext
|
||||
{
|
||||
}
|
||||
|
||||
private record State(
|
||||
[property: JsonPropertyName("Reason")] string Reason,
|
||||
[property: JsonPropertyName("ReasonTTL")] string ReasonTTL,
|
||||
[property: JsonPropertyName("State")] string Value
|
||||
);
|
||||
|
||||
[JsonSourceGenerationOptions(WriteIndented = true, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
[JsonSerializable(typeof(State))]
|
||||
private partial class StateSourceGenerationContext : JsonSerializerContext
|
||||
{
|
||||
}
|
||||
|
||||
private record Status(
|
||||
[property: JsonPropertyName("Reason")] string Reason,
|
||||
[property: JsonPropertyName("State")] string State
|
||||
);
|
||||
|
||||
[JsonSourceGenerationOptions(WriteIndented = true, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
[JsonSerializable(typeof(Status))]
|
||||
private partial class StatusSourceGenerationContext : JsonSerializerContext
|
||||
{
|
||||
}
|
||||
|
||||
private record TCPSequence(
|
||||
[property: JsonPropertyName("Difficulty")] string Difficulty,
|
||||
[property: JsonPropertyName("Index")] string Index,
|
||||
[property: JsonPropertyName("Values")] string Values
|
||||
);
|
||||
|
||||
[JsonSourceGenerationOptions(WriteIndented = true, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
[JsonSerializable(typeof(TCPSequence))]
|
||||
private partial class TCPSequenceSourceGenerationContext : JsonSerializerContext
|
||||
{
|
||||
}
|
||||
|
||||
private record TCPTSSequence(
|
||||
[property: JsonPropertyName("Class")] string Class,
|
||||
[property: JsonPropertyName("Values")] string Values
|
||||
);
|
||||
|
||||
[JsonSourceGenerationOptions(WriteIndented = true, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
[JsonSerializable(typeof(TCPTSSequence))]
|
||||
private partial class TCPTSSequenceSourceGenerationContext : JsonSerializerContext
|
||||
{
|
||||
}
|
||||
|
||||
private record Trace(
|
||||
[property: JsonPropertyName("Hops")] IReadOnlyList<Hop> Hops,
|
||||
[property: JsonPropertyName("Port")] int Port,
|
||||
[property: JsonPropertyName("Protocol")] string Protocol
|
||||
);
|
||||
|
||||
[JsonSourceGenerationOptions(WriteIndented = true, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
[JsonSerializable(typeof(Trace))]
|
||||
private partial class TraceSourceGenerationContext : JsonSerializerContext
|
||||
{
|
||||
}
|
||||
|
||||
private record Uptime(
|
||||
[property: JsonPropertyName("LastBoot")] string LastBoot,
|
||||
[property: JsonPropertyName("Seconds")] int Seconds
|
||||
);
|
||||
|
||||
[JsonSourceGenerationOptions(WriteIndented = true, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
[JsonSerializable(typeof(Uptime))]
|
||||
private partial class UptimeSourceGenerationContext : JsonSerializerContext
|
||||
{
|
||||
}
|
||||
|
||||
private record Verbose(
|
||||
[property: JsonPropertyName("Level")] int Level
|
||||
);
|
||||
|
||||
[JsonSourceGenerationOptions(WriteIndented = true, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
[JsonSerializable(typeof(Verbose))]
|
||||
private partial class VerboseSourceGenerationContext : JsonSerializerContext
|
||||
{
|
||||
}
|
||||
|
||||
private static string[] GetIPV4Segments(string value)
|
||||
{
|
||||
string[] result;
|
||||
string[] subSegments = value.Split('.');
|
||||
if (subSegments.Length != 4)
|
||||
result = [];
|
||||
else
|
||||
{
|
||||
if (!subSegments.All(l => int.TryParse(l, out _)))
|
||||
result = [];
|
||||
else
|
||||
result = value.Split('.');
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static ReadOnlyCollection<ReadOnlyCollection<string>> GetHostLinesSpaceSegments()
|
||||
{
|
||||
List<ReadOnlyCollection<string>> results = [];
|
||||
string hostFile = "C:/Windows/System32/drivers/etc/hosts";
|
||||
string[] lines = !File.Exists(hostFile) ? [] : File.ReadAllLines(hostFile);
|
||||
foreach (string line in lines)
|
||||
results.Add(new(line.Split(' ')));
|
||||
return new(results);
|
||||
}
|
||||
|
||||
private static string[] GetMacAddressSegments(string value)
|
||||
{
|
||||
string[] result;
|
||||
if (value.Length != 17)
|
||||
result = [];
|
||||
else
|
||||
{
|
||||
string v = value.ToLower();
|
||||
if (v[2] is not ':' or '-' || v[5] is not ':' or '-' || v[8] is not ':' or '-' || v[11] is not ':' or '-' || v[14] is not ':' or '-')
|
||||
result = [];
|
||||
else
|
||||
{
|
||||
result = [$"{v[0]}{v[1]}", $"{v[3]}{v[4]}", $"{v[6]}{v[7]}", $"{v[9]}{v[10]}", $"{v[12]}{v[13]}", $"{v[15]}{v[16]}"];
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
internal static void SplitJsonFile(ILogger<Worker> logger, List<string> args)
|
||||
{
|
||||
string json;
|
||||
string title;
|
||||
Record? record;
|
||||
string fileName;
|
||||
FileInfo fileInfo;
|
||||
string checkFileName;
|
||||
string sourceFileName;
|
||||
string[] ipV4Segments;
|
||||
string outputDirectory;
|
||||
List<string> lines = [];
|
||||
List<string> links = [];
|
||||
List<string> allLines = [];
|
||||
string[] macAddressSegments;
|
||||
string macAddressWithHyphens;
|
||||
string ipV4SegmentsWithPeriods;
|
||||
List<string> titleSegments = [];
|
||||
string fileNameWithoutExtension;
|
||||
const int ipV4SegmentsLength = 4;
|
||||
string sourceDirectory = args[0];
|
||||
const int macAddressSegmentsLength = 6;
|
||||
string[] fileNameWithoutExtensionSegments;
|
||||
string fileNameWithoutExtensionFirstThreeSegments;
|
||||
if (!Directory.Exists(sourceDirectory))
|
||||
throw new Exception(sourceDirectory);
|
||||
List<ReadOnlyCollection<string>> hostLineMatchSpaceSegments;
|
||||
ReadOnlyCollection<ReadOnlyCollection<string>> hostLinesSpaceSegments = GetHostLinesSpaceSegments();
|
||||
string[] files = Directory.GetFiles(sourceDirectory, args[2], SearchOption.TopDirectoryOnly);
|
||||
foreach (string file in files)
|
||||
{
|
||||
links.Clear();
|
||||
fileInfo = new(file);
|
||||
json = File.ReadAllText(file);
|
||||
fileNameWithoutExtension = Path.GetFileNameWithoutExtension(file);
|
||||
outputDirectory = Path.Combine(sourceDirectory, fileNameWithoutExtension);
|
||||
fileNameWithoutExtensionSegments = GetIPV4Segments(fileNameWithoutExtension);
|
||||
if (fileNameWithoutExtensionSegments.Length != ipV4SegmentsLength)
|
||||
continue;
|
||||
fileNameWithoutExtensionFirstThreeSegments = $"{fileNameWithoutExtensionSegments[0]}.{fileNameWithoutExtensionSegments[1]}.{fileNameWithoutExtensionSegments[2]}.";
|
||||
if (!Directory.Exists(outputDirectory))
|
||||
_ = Directory.CreateDirectory(outputDirectory);
|
||||
record = JsonSerializer.Deserialize(json, RecordSourceGenerationContext.Default.Record);
|
||||
if (record is null)
|
||||
continue;
|
||||
foreach (Host host in record.Hosts)
|
||||
{
|
||||
lines.Clear();
|
||||
ipV4Segments = [];
|
||||
titleSegments.Clear();
|
||||
macAddressSegments = [];
|
||||
foreach (HostAddress hostAddress in host.HostAddresses)
|
||||
{
|
||||
if (hostAddress.AddressType == "ipv4")
|
||||
ipV4Segments = GetIPV4Segments(hostAddress.Address);
|
||||
else if (hostAddress.AddressType == "mac")
|
||||
macAddressSegments = GetMacAddressSegments(hostAddress.Address);
|
||||
else
|
||||
continue;
|
||||
}
|
||||
if (ipV4Segments.Length != ipV4SegmentsLength)
|
||||
continue;
|
||||
ipV4SegmentsWithPeriods = string.Join('.', ipV4Segments);
|
||||
macAddressWithHyphens = string.Join('-', macAddressSegments);
|
||||
if (macAddressSegments.Length != macAddressSegmentsLength)
|
||||
hostLineMatchSpaceSegments = (from l in hostLinesSpaceSegments where l.Count > 0 && l.Contains(ipV4SegmentsWithPeriods) select l).ToList();
|
||||
else
|
||||
{
|
||||
hostLineMatchSpaceSegments = (from l in hostLinesSpaceSegments where l.Count > 0 && l.Contains(macAddressWithHyphens) select l).ToList();
|
||||
if (hostLineMatchSpaceSegments.Count == 1)
|
||||
title = string.Join(' ', hostLineMatchSpaceSegments[0]);
|
||||
else
|
||||
hostLineMatchSpaceSegments = (from l in hostLineMatchSpaceSegments where l.Count > 0 && l[0].StartsWith(fileNameWithoutExtensionFirstThreeSegments) select l).ToList();
|
||||
}
|
||||
if (ipV4Segments.Length == ipV4SegmentsLength)
|
||||
titleSegments.Add(ipV4SegmentsWithPeriods);
|
||||
if (hostLineMatchSpaceSegments.Count == 1)
|
||||
title = $"{ipV4SegmentsWithPeriods} {string.Join(' ', hostLineMatchSpaceSegments[0].Skip(1))}";
|
||||
else
|
||||
{
|
||||
if (host.HostNames.HostName is null)
|
||||
titleSegments.Add("unknown #");
|
||||
else
|
||||
titleSegments.Add($"{string.Join("_", host.HostNames.HostName.Select(l => l.Name.Replace(' ', '-')))} #");
|
||||
if (macAddressSegments.Length == macAddressSegmentsLength)
|
||||
titleSegments.Add(macAddressWithHyphens);
|
||||
title = string.Join(" ", titleSegments);
|
||||
logger.LogInformation("{title} Type DeviceInfo ~ needs to be added to host file!", title);
|
||||
}
|
||||
json = JsonSerializer.Serialize(host, HostSourceGenerationContext.Default.Host);
|
||||
fileNameWithoutExtension = macAddressSegments.Length != macAddressSegmentsLength ? $"ipv4-{string.Join(string.Empty, ipV4Segments)}" : $"mac-{string.Join(string.Empty, macAddressSegments)}";
|
||||
fileName = $"{fileNameWithoutExtension}.md";
|
||||
links.Add($"- [{title}]({fileName})");
|
||||
lines.Add("---");
|
||||
allLines.Add(title);
|
||||
lines.Add(string.Empty);
|
||||
lines.Add($"# {title}");
|
||||
lines.Add(string.Empty);
|
||||
lines.Add($"## {fileNameWithoutExtension}");
|
||||
if (host.Ports is not null)
|
||||
{
|
||||
lines.Add(string.Empty);
|
||||
lines.Add("## Port(s)");
|
||||
lines.Add(string.Empty);
|
||||
lines.Add("| Id | Protocol | State | Service |");
|
||||
lines.Add("| - | - | - | - |");
|
||||
foreach (Port port in host.Ports)
|
||||
lines.Add($"| {port.PortID} | {port.Protocol} | {port.State.Value} | {port.Service.Name} |");
|
||||
}
|
||||
lines.Add(string.Empty);
|
||||
lines.Add("```json");
|
||||
lines.Add(json);
|
||||
lines.Add("```");
|
||||
checkFileName = Path.Combine(outputDirectory, fileName);
|
||||
if (File.Exists(checkFileName))
|
||||
File.Delete(checkFileName);
|
||||
File.WriteAllLines(checkFileName, lines);
|
||||
File.SetCreationTime(checkFileName, fileInfo.CreationTime);
|
||||
File.SetLastWriteTime(checkFileName, fileInfo.LastWriteTime);
|
||||
logger.LogInformation("{title} created", title);
|
||||
}
|
||||
lines.Clear();
|
||||
record.Hosts.Clear();
|
||||
title = Path.GetFileNameWithoutExtension(file);
|
||||
json = JsonSerializer.Serialize(record, RecordSourceGenerationContext.Default.Record);
|
||||
lines.Add("---");
|
||||
lines.Add(string.Empty);
|
||||
lines.Add($"# {title}");
|
||||
lines.Add(string.Empty);
|
||||
lines.Add($"## {title}");
|
||||
lines.Add(string.Empty);
|
||||
lines.Add("## Hosts");
|
||||
lines.Add(string.Empty);
|
||||
lines.AddRange(links);
|
||||
lines.Add(string.Empty);
|
||||
lines.Add("```json");
|
||||
lines.Add(json);
|
||||
lines.Add("```");
|
||||
checkFileName = Path.Combine(outputDirectory, $"{title}.md");
|
||||
if (File.Exists(checkFileName))
|
||||
File.Delete(checkFileName);
|
||||
File.WriteAllLines(checkFileName, lines);
|
||||
File.SetCreationTime(checkFileName, fileInfo.CreationTime);
|
||||
File.SetLastWriteTime(checkFileName, fileInfo.LastWriteTime);
|
||||
logger.LogInformation("{title} created", title);
|
||||
checkFileName = Path.Combine(outputDirectory, Path.GetFileName(file));
|
||||
if (File.Exists(checkFileName))
|
||||
File.Delete(checkFileName);
|
||||
File.Move(file, checkFileName);
|
||||
checkFileName = Path.Combine(outputDirectory, $"{Path.GetFileNameWithoutExtension(file)}.xml");
|
||||
if (File.Exists(checkFileName))
|
||||
File.Delete(checkFileName);
|
||||
sourceFileName = Path.ChangeExtension(file, ".xml");
|
||||
if (File.Exists(sourceFileName))
|
||||
File.Move(sourceFileName, checkFileName);
|
||||
}
|
||||
File.WriteAllLines(Path.Combine(sourceDirectory, $"{DateTime.Now.Ticks}.ssv"), allLines);
|
||||
}
|
||||
|
||||
}
|
@ -1,4 +1,6 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
@ -7,14 +9,30 @@ namespace File_Folder_Helper.Day;
|
||||
internal static partial class Helper20240106
|
||||
{
|
||||
|
||||
private record Host([property: JsonPropertyName("a")] string? Id,
|
||||
[property: JsonPropertyName("b")] string? Colon,
|
||||
[property: JsonPropertyName("c")] string? Hyphen,
|
||||
[property: JsonPropertyName("d")] string? Line,
|
||||
[property: JsonPropertyName("e")] string? Count,
|
||||
[property: JsonPropertyName("f")] string? Segments,
|
||||
[property: JsonPropertyName("g")] string? Type,
|
||||
[property: JsonPropertyName("h")] string? Device,
|
||||
[property: JsonPropertyName("i")] string? Name);
|
||||
|
||||
[JsonSourceGenerationOptions(WriteIndented = true, AllowTrailingCommas = true)]
|
||||
[JsonSerializable(typeof(Host[]))]
|
||||
private partial class HostSourceGenerationContext : JsonSerializerContext
|
||||
{
|
||||
}
|
||||
|
||||
private record Record(string Key, Dictionary<string, string> KeyValuePairs);
|
||||
|
||||
[JsonSourceGenerationOptions(WriteIndented = true)]
|
||||
[JsonSerializable(typeof(Dictionary<string, Dictionary<string, string>>))]
|
||||
private partial class DictionaryDictionarySourceGenerationContext : JsonSerializerContext
|
||||
{
|
||||
}
|
||||
|
||||
private record Record(string Key, Dictionary<string, string> KeyValuePairs);
|
||||
|
||||
private static Dictionary<string, Dictionary<string, string>> GetKeyValuePairs(List<Record> collection, bool replaceFound)
|
||||
{
|
||||
Dictionary<string, Dictionary<string, string>> results = [];
|
||||
@ -94,18 +112,116 @@ internal static partial class Helper20240106
|
||||
return results;
|
||||
}
|
||||
|
||||
private static Dictionary<int, Host> GetHosts(string jsonl)
|
||||
{
|
||||
Dictionary<int, Host> results = [];
|
||||
int id;
|
||||
string json = $"[{File.ReadAllText(jsonl).Replace("\r\n", ",")}]";
|
||||
Host[] hosts = JsonSerializer.Deserialize(json, HostSourceGenerationContext.Default.HostArray) ?? throw new NullReferenceException(nameof(json));
|
||||
foreach (Host host in hosts)
|
||||
{
|
||||
if (host.Id is null)
|
||||
continue;
|
||||
if (host.Hyphen is not null and nameof(host.Hyphen))
|
||||
continue;
|
||||
if (!int.TryParse(host.Id, out id))
|
||||
throw new NotSupportedException($"{host.Id} is not a number");
|
||||
if (results.ContainsKey(id))
|
||||
throw new NotSupportedException($"Id {id} is not unique!");
|
||||
results.Add(id, host);
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
private static ReadOnlyCollection<string> GetIpAddressAndVerify(ILogger<Worker> logger, string key, Dictionary<string, Dictionary<string, string>> keyValuePairs, Dictionary<int, Host> hosts)
|
||||
{
|
||||
List<string> results = [];
|
||||
int id;
|
||||
bool found;
|
||||
Host? host;
|
||||
string text;
|
||||
string? ipAddress;
|
||||
StringBuilder stringBuilder = new();
|
||||
foreach (KeyValuePair<string, Dictionary<string, string>> keyValuePair in keyValuePairs)
|
||||
{
|
||||
found = false;
|
||||
if (!keyValuePair.Value.TryGetValue(key, out ipAddress))
|
||||
throw new NotSupportedException($"{key} isn't present!");
|
||||
if (ipAddress == "0.0.0.0")
|
||||
continue;
|
||||
results.Add(ipAddress);
|
||||
_ = stringBuilder.Clear();
|
||||
foreach (KeyValuePair<string, string> keyValue in keyValuePair.Value)
|
||||
_ = stringBuilder.AppendLine(keyValue.Value);
|
||||
text = stringBuilder.ToString();
|
||||
if (!int.TryParse(ipAddress.Split('.')[^1], out id))
|
||||
throw new NotSupportedException($"{ipAddress} isn't valid!");
|
||||
if (!hosts.TryGetValue(id, out host))
|
||||
throw new NotSupportedException($"{id} isn't valid!");
|
||||
foreach (KeyValuePair<string, string> keyValue in keyValuePair.Value)
|
||||
{
|
||||
if (keyValue.Value != host.Hyphen)
|
||||
continue;
|
||||
found = true;
|
||||
}
|
||||
if (!found)
|
||||
throw new NotSupportedException($"{host}{Environment.NewLine}{text} doesn't match!");
|
||||
if (text.Contains("Unknown", StringComparison.InvariantCultureIgnoreCase))
|
||||
logger.LogWarning($"{text} contains Unknown and should be {host.Device}!");
|
||||
}
|
||||
return new(results);
|
||||
}
|
||||
|
||||
private static void WriteAppendToHostConfFile(FileInfo fileInfo, string hostConfFile, Dictionary<int, Host> hosts, ReadOnlyCollection<string> ipAddress)
|
||||
{
|
||||
int id;
|
||||
Host host;
|
||||
string ip;
|
||||
string line;
|
||||
List<int> distinct = [];
|
||||
List<string> lines = [$"# {fileInfo.LastWriteTime.Ticks}"];
|
||||
string firstSegmentsOfIpAddress = string.Join('.', ipAddress[0].Split('.').Take(3));
|
||||
foreach (KeyValuePair<int, Host> keyValuePair in hosts)
|
||||
{
|
||||
host = keyValuePair.Value;
|
||||
if (host.Hyphen is not null and nameof(host.Hyphen))
|
||||
continue;
|
||||
if (host.Id is null || host.Hyphen is null || host.Device is null || host.Name is null || host.Hyphen.Length != 17)
|
||||
throw new NotSupportedException($"{host.Id} is Null or not 17");
|
||||
if (!int.TryParse(host.Id, out id))
|
||||
throw new NotSupportedException($"{host.Id} is not a number");
|
||||
if (distinct.Contains(id))
|
||||
throw new NotSupportedException($"{id} is not distinct!");
|
||||
distinct.Add(id);
|
||||
ip = ipAddress.Contains($"{firstSegmentsOfIpAddress}.{id}") ? $"{firstSegmentsOfIpAddress}.{id}" : $"# {firstSegmentsOfIpAddress}.{id}";
|
||||
line = $"{ip} {host.Name} # https://{host.Name} | {host.Colon} | {host.Hyphen} | {host.Device} |";
|
||||
lines.Add(line);
|
||||
}
|
||||
lines.Add($"# {fileInfo.LastWriteTime.Ticks}");
|
||||
File.AppendAllLines(hostConfFile, lines);
|
||||
}
|
||||
|
||||
internal static void TextToJson(ILogger<Worker> logger, List<string> args)
|
||||
{
|
||||
string json;
|
||||
string[] lines;
|
||||
int? headerLine;
|
||||
FileInfo fileInfo;
|
||||
string replace = args[6];
|
||||
int keyIndex = int.Parse(args[4]);
|
||||
int keyLength = int.Parse(args[5]);
|
||||
string[] headers = args[7].Split(',');
|
||||
string key = args[7];
|
||||
string replace = args[5];
|
||||
int keyIndex = int.Parse(args[3]);
|
||||
int keyLength = int.Parse(args[4]);
|
||||
ReadOnlyCollection<string> ipAddress;
|
||||
string[] headers = args[6].Split(',');
|
||||
string jsonl = Path.Combine(args[0], args[8]);
|
||||
string hostConfFile = Path.Combine(args[0], args[9]);
|
||||
string[] txtFiles = Directory.GetFiles(args[0], args[2]);
|
||||
Dictionary<string, Dictionary<string, string>> keyValuePairs;
|
||||
if (!File.Exists(jsonl))
|
||||
throw new NotSupportedException($"{args[8]} doesn't exist!");
|
||||
Dictionary<int, Host> hosts = GetHosts(jsonl);
|
||||
if (hosts.Count == 0)
|
||||
throw new NotSupportedException($"{args[8]} isn't valid!");
|
||||
foreach (string txtFile in txtFiles)
|
||||
{
|
||||
lines = File.ReadAllLines(txtFile);
|
||||
@ -118,10 +234,14 @@ internal static partial class Helper20240106
|
||||
keyValuePairs = GetKeyValuePairs(keyIndex, keyLength, replace, headers, lines, headerLine.Value);
|
||||
if (keyValuePairs.Count == 0)
|
||||
continue;
|
||||
ipAddress = GetIpAddressAndVerify(logger, key, keyValuePairs, hosts);
|
||||
if (ipAddress.Count == 0)
|
||||
continue;
|
||||
json = JsonSerializer.Serialize(keyValuePairs, DictionaryDictionarySourceGenerationContext.Default.DictionaryStringDictionaryStringString);
|
||||
logger.LogInformation("Writing output file...");
|
||||
File.WriteAllText($"{txtFile}-{fileInfo.LastWriteTime.Ticks}.json", json);
|
||||
File.WriteAllText(txtFile, string.Empty);
|
||||
File.WriteAllText($"{fileInfo.FullName}-{fileInfo.LastWriteTime.Ticks}.json", json);
|
||||
WriteAppendToHostConfFile(fileInfo, hostConfFile, hosts, ipAddress);
|
||||
File.WriteAllLines(txtFile, [string.Empty, string.Empty, lines[^1]]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,16 +6,20 @@ namespace File_Folder_Helper.Day;
|
||||
internal static partial class Helper20240107
|
||||
{
|
||||
|
||||
private static void DirectoryToISO(ILogger<Worker> logger, string destinationDirectory, string directory)
|
||||
private static void DirectoryToISO(ILogger<Worker> logger, string destinationDirectory, bool mapOnly, string directory)
|
||||
{
|
||||
byte[] bytes = [];
|
||||
string relativePath;
|
||||
string directoryName = Path.GetFileName(directory);
|
||||
CDBuilder builder = new() { UseJoliet = true, VolumeIdentifier = directoryName };
|
||||
IEnumerable<string> files = Directory.EnumerateFiles(directory, "*", SearchOption.AllDirectories);
|
||||
CDBuilder builder = new() { UseJoliet = true, VolumeIdentifier = directoryName.Length < 25 ? directoryName : directoryName[..25] };
|
||||
IEnumerable<string> files = Directory.EnumerateFiles(directory, "*", new EnumerationOptions { IgnoreInaccessible = true, RecurseSubdirectories = true });
|
||||
foreach (string file in files)
|
||||
{
|
||||
relativePath = Path.GetRelativePath(directory, file);
|
||||
_ = builder.AddFile(relativePath, file);
|
||||
relativePath = Path.GetRelativePath(directory, file).Replace(';', '_');
|
||||
if (!mapOnly)
|
||||
_ = builder.AddFile(relativePath, file);
|
||||
else
|
||||
_ = builder.AddFile(relativePath, bytes);
|
||||
}
|
||||
logger.LogInformation(destinationDirectory);
|
||||
builder.Build(Path.Combine(destinationDirectory, $"{directoryName}.iso"));
|
||||
@ -28,11 +32,16 @@ internal static partial class Helper20240107
|
||||
int directories = int.Parse(args[2]);
|
||||
string destinationDirectory = args[3];
|
||||
logger.LogInformation(sourceDirectory);
|
||||
if (sourceDirectory == "C:/ProgramData")
|
||||
sourceDirectory = destinationDirectory;
|
||||
bool mapOnly = sourceDirectory.Length == 2;
|
||||
if (!Directory.Exists(destinationDirectory))
|
||||
_ = Directory.CreateDirectory(destinationDirectory);
|
||||
string[] subDirectories = directories == 1 ? [sourceDirectory] : Directory.GetDirectories(sourceDirectory, "*", SearchOption.TopDirectoryOnly);
|
||||
if (subDirectories.Length != directories)
|
||||
throw new Exception($"{directories} != {subDirectories.Length}");
|
||||
foreach (string directory in subDirectories)
|
||||
DirectoryToISO(logger, destinationDirectory, directory);
|
||||
DirectoryToISO(logger, destinationDirectory, mapOnly, directory);
|
||||
}
|
||||
|
||||
}
|
@ -81,7 +81,7 @@ internal static partial class Helper20240108
|
||||
return result;
|
||||
}
|
||||
|
||||
private static int? GetFirstUsedLine(string[] lines, int i, string search, string searchNot, string searchWrap, string searchConstructor, int parameterCount)
|
||||
private static int? GetFirstUsedLine(string[] lines, int i, string search, string searchNot, string searchWrap, string searchDelegate, string searchConstructor, int parameterCount)
|
||||
{
|
||||
int? result = null;
|
||||
string[] segments;
|
||||
@ -100,26 +100,37 @@ internal static partial class Helper20240108
|
||||
segments = lines[j].Split(searchWrap);
|
||||
if (segments.Length == 1)
|
||||
{
|
||||
segments = lines[j].Split(searchConstructor);
|
||||
if (segments.Length == 1)
|
||||
continue;
|
||||
if (!lines[j].EndsWith(searchDelegate))
|
||||
{
|
||||
segments = lines[j].Split(searchConstructor);
|
||||
if (segments.Length == 1)
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
lastSegmentBeforeDot = segments[^1].Split(").")[0];
|
||||
if (parameterCount == 0)
|
||||
if (lines[j].EndsWith(searchDelegate))
|
||||
{
|
||||
if (lastSegmentBeforeDot.Contains(','))
|
||||
continue;
|
||||
result = j;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
afterSegments = lastSegmentBeforeDot.Split(',');
|
||||
if (afterSegments.Length != parameterCount)
|
||||
continue;
|
||||
lastSegmentBeforeDot = segments[^1].Split(").")[0];
|
||||
if (parameterCount == 0)
|
||||
{
|
||||
if (lastSegmentBeforeDot.Contains(','))
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
afterSegments = lastSegmentBeforeDot.Split(',');
|
||||
if (afterSegments.Length != parameterCount)
|
||||
continue;
|
||||
}
|
||||
result = j;
|
||||
break;
|
||||
}
|
||||
result = j;
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -150,6 +161,7 @@ internal static partial class Helper20240108
|
||||
string searchWrap;
|
||||
int parameterCount;
|
||||
int? firstUsedLine;
|
||||
string searchDelegate;
|
||||
string lineSegmentFirst;
|
||||
string searchConstructor;
|
||||
for (int i = 0; i < lines.Length; i++)
|
||||
@ -167,11 +179,12 @@ internal static partial class Helper20240108
|
||||
search = $" {name}(";
|
||||
searchNot = $"!{name}(";
|
||||
searchWrap = $"({name}(";
|
||||
searchDelegate = $" += {name};";
|
||||
if (string.IsNullOrEmpty(name))
|
||||
continue;
|
||||
blocks = 0;
|
||||
searchConstructor = $"{name.ToLower()} = new(";
|
||||
startLine = GetStartLine(lines, i);
|
||||
searchConstructor = $"{name.ToLower()} = new(";
|
||||
parameterCount = GetParameterCount(line, search);
|
||||
isLinq = lines[i + 1].Trim() != "{";
|
||||
if (isLinq)
|
||||
@ -190,7 +203,7 @@ internal static partial class Helper20240108
|
||||
endLine = j;
|
||||
if (lines.Length > j + 1 && string.IsNullOrEmpty(lines[j + 1].Trim()))
|
||||
endLine++;
|
||||
firstUsedLine = GetFirstUsedLine(lines, i, search, searchNot, searchWrap, searchConstructor, parameterCount);
|
||||
firstUsedLine = GetFirstUsedLine(lines, i, search, searchNot, searchWrap, searchDelegate, searchConstructor, parameterCount);
|
||||
if (firstUsedLine is null)
|
||||
{
|
||||
lineSegmentFirst = line.Split(search)[0];
|
||||
@ -255,18 +268,24 @@ internal static partial class Helper20240108
|
||||
return result;
|
||||
}
|
||||
|
||||
internal static void SortCodeMethods(ILogger<Worker> logger, List<string> args)
|
||||
internal static void SortCodeMethods(ILogger<Worker> logger, List<string> args, CancellationToken cancellationToken)
|
||||
{
|
||||
bool result = false;
|
||||
bool check;
|
||||
string[] lines;
|
||||
bool usePathCombine = true;
|
||||
long ticks = DateTime.Now.Ticks;
|
||||
logger.LogInformation("{ticks}", ticks);
|
||||
string[] cSharpFiles = Directory.GetFiles(args[0], "*.cs", SearchOption.TopDirectoryOnly);
|
||||
string directory = Path.GetFullPath(args[2]);
|
||||
string repositoryDirectory = Path.GetFullPath(args[0]);
|
||||
string[] cSharpFiles = Directory.GetFiles(directory, "*.cs", SearchOption.AllDirectories);
|
||||
ReadOnlyCollection<string> gitOthersModifiedAndDeletedExcludingStandardFiles = Helpers.HelperGit.GetOthersModifiedAndDeletedExcludingStandardFiles(repositoryDirectory, usePathCombine, cancellationToken);
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
foreach (string cSharpFile in cSharpFiles)
|
||||
{
|
||||
if (!gitOthersModifiedAndDeletedExcludingStandardFiles.Contains(cSharpFile))
|
||||
continue;
|
||||
lines = File.ReadAllLines(cSharpFile);
|
||||
check = SortFile(logger, cSharpFile, lines);
|
||||
if (check && !result)
|
||||
|
83
Day/2024-Q1/Helper-2024-01-29.cs
Normal file
83
Day/2024-Q1/Helper-2024-01-29.cs
Normal file
@ -0,0 +1,83 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace File_Folder_Helper.Day;
|
||||
|
||||
internal static partial class Helper20240129
|
||||
{
|
||||
|
||||
private record Record([property: JsonPropertyName("Part Name")] string? PartName,
|
||||
[property: JsonPropertyName("Part Revision")] string? PartRevision,
|
||||
[property: JsonPropertyName("Test Name")] string? TestName,
|
||||
[property: JsonPropertyName("Description")] string? Description,
|
||||
[property: JsonPropertyName("Lot Number")] string? LotNumber,
|
||||
[property: JsonPropertyName("Job Name")] string? JobName,
|
||||
[property: JsonPropertyName("Process Name")] string? ProcessName,
|
||||
[property: JsonPropertyName("Reasonable Limit (Upper)")] double? ReasonableLimitUpper,
|
||||
[property: JsonPropertyName("Alarm Reasonable Limit (Upper)")] double? AlarmReasonableLimitUpper,
|
||||
[property: JsonPropertyName("Specification Limit (Upper)")] double? SpecificationLimitUpper,
|
||||
[property: JsonPropertyName("Alarm Specification Limit (Upper)")] double? AlarmSpecificationLimitUpper,
|
||||
[property: JsonPropertyName("Warning Limit (Upper)")] double? WarningLimitUpper,
|
||||
[property: JsonPropertyName("Alarm Warning Limit (Upper)")] double? AlarmWarningLimitUpper,
|
||||
[property: JsonPropertyName("Specification Limit (Target)")] double? SpecificationLimitTarget,
|
||||
[property: JsonPropertyName("Warning Limit (Lower)")] double? WarningLimitLower,
|
||||
[property: JsonPropertyName("Alarm Warning Limit (Lower)")] double? AlarmWarningLimitLower,
|
||||
[property: JsonPropertyName("Specification Limit (Lower)")] double? SpecificationLimitLower,
|
||||
[property: JsonPropertyName("Alarm Specification Limit (Lower)")] double? AlarmSpecificationLimitLower,
|
||||
[property: JsonPropertyName("Reasonable Limit (Lower)")] double? ReasonableLimitLower,
|
||||
[property: JsonPropertyName("Alarm Reasonable Limit (Lower)")] double? AlarmReasonableLimitLower,
|
||||
[property: JsonPropertyName("Original Test Name")] string? OriginalTestName,
|
||||
[property: JsonPropertyName("Test Id")] int? TestId,
|
||||
[property: JsonPropertyName("count")] int? Count);
|
||||
|
||||
[JsonSourceGenerationOptions(WriteIndented = true, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
[JsonSerializable(typeof(Record[]))]
|
||||
private partial class Helper20240129RecordCollectionSourceGenerationContext : JsonSerializerContext
|
||||
{
|
||||
}
|
||||
|
||||
private static List<string> GetLines(Record[] records)
|
||||
{
|
||||
List<string> lines = [];
|
||||
lines.Add($"{nameof(Record.PartName)}\t{nameof(Record.PartRevision)}\t{nameof(Record.TestName)}\t{nameof(Record.Description)}\t{nameof(Record.LotNumber)}\t{nameof(Record.JobName)}\t{nameof(Record.ProcessName)}\t{nameof(Record.ReasonableLimitUpper)}\t{nameof(Record.AlarmReasonableLimitUpper)}\t{nameof(Record.SpecificationLimitUpper)}\t{nameof(Record.AlarmSpecificationLimitUpper)}\t{nameof(Record.WarningLimitUpper)}\t{nameof(Record.AlarmWarningLimitUpper)}\t{nameof(Record.SpecificationLimitTarget)}\t{nameof(Record.WarningLimitLower)}\t{nameof(Record.AlarmWarningLimitLower)}\t{nameof(Record.SpecificationLimitLower)}\t{nameof(Record.AlarmSpecificationLimitLower)}\t{nameof(Record.ReasonableLimitLower)}\t{nameof(Record.AlarmReasonableLimitLower)}\t{nameof(Record.OriginalTestName)}\t{nameof(Record.TestId)}\t{nameof(Record.Count)}");
|
||||
foreach (Record record in records)
|
||||
lines.Add($"{record.PartName}\t{record.PartRevision}\t{record.TestName}\t{record.Description}\t{record.LotNumber}\t{record.JobName}\t{record.ProcessName}\t{record.ReasonableLimitUpper}\t{record.AlarmReasonableLimitUpper}\t{record.SpecificationLimitUpper}\t{record.AlarmSpecificationLimitUpper}\t{record.WarningLimitUpper}\t{record.AlarmWarningLimitUpper}\t{record.SpecificationLimitTarget}\t{record.WarningLimitLower}\t{record.AlarmWarningLimitLower}\t{record.SpecificationLimitLower}\t{record.AlarmSpecificationLimitLower}\t{record.ReasonableLimitLower}\t{record.AlarmReasonableLimitLower}\t{record.OriginalTestName}\t{record.TestId}\t{record.Count}");
|
||||
return lines;
|
||||
}
|
||||
|
||||
private static void ConvertAndWrite(string pattern, string sourceDirectory)
|
||||
{
|
||||
long ticks;
|
||||
string json;
|
||||
string fileName;
|
||||
string checkFile;
|
||||
Record[]? records;
|
||||
List<string> lines;
|
||||
string[] files = Directory.GetFiles(sourceDirectory, pattern, SearchOption.TopDirectoryOnly);
|
||||
foreach (string file in files)
|
||||
{
|
||||
ticks = DateTime.Now.Ticks;
|
||||
json = File.ReadAllText(file);
|
||||
fileName = Path.GetFileName(file);
|
||||
checkFile = Path.Combine(sourceDirectory, $"{fileName}.{ticks}.tsv");
|
||||
records = JsonSerializer.Deserialize(json, Helper20240129RecordCollectionSourceGenerationContext.Default.RecordArray);
|
||||
if (records is null)
|
||||
continue;
|
||||
lines = GetLines(records);
|
||||
File.WriteAllLines(checkFile, lines);
|
||||
checkFile = Path.Combine(sourceDirectory, $"{fileName}.{ticks}.done");
|
||||
File.Move(file, checkFile);
|
||||
Thread.Sleep(100);
|
||||
}
|
||||
}
|
||||
|
||||
internal static void JsonToTsv(ILogger<Worker> logger, List<string> args)
|
||||
{
|
||||
string pattern = args[2];
|
||||
string sourceDirectory = args[0];
|
||||
logger.LogInformation(sourceDirectory);
|
||||
ConvertAndWrite(pattern, sourceDirectory);
|
||||
}
|
||||
|
||||
}
|
58
Day/2024-Q1/Helper-2024-03-05.cs
Normal file
58
Day/2024-Q1/Helper-2024-03-05.cs
Normal file
@ -0,0 +1,58 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Globalization;
|
||||
|
||||
namespace File_Folder_Helper.Day;
|
||||
|
||||
internal static partial class Helper20240305
|
||||
{
|
||||
|
||||
private static void TryArchiveFiles(string sourceDirectory, string pattern, string archiveDirectory, string days)
|
||||
{
|
||||
string checkFile;
|
||||
FileInfo fileInfo;
|
||||
string weekOfYear;
|
||||
string checkDirectory;
|
||||
string[] directorySegments;
|
||||
Calendar calendar = new CultureInfo("en-US").Calendar;
|
||||
DateTime dateTime = DateTime.Now.AddDays(-int.Parse(days));
|
||||
string[] sourceDirectorySegments = sourceDirectory.Split('/');
|
||||
// DirectoryInfo directoryInfo = new(Path.GetFullPath(sourceDirectory));
|
||||
// IEnumerable<FileInfo> fileInfoCollection = directoryInfo.EnumerateFiles(pattern, new EnumerationOptions { IgnoreInaccessible = true, RecurseSubdirectories = true });
|
||||
string[] files = Directory.GetFiles(sourceDirectory, pattern, SearchOption.AllDirectories);
|
||||
if (!sourceDirectory.StartsWith('\\') && sourceDirectorySegments.Length < 2)
|
||||
throw new Exception("Can't be root drive!");
|
||||
// foreach (FileInfo fileInfo in fileInfoCollection)
|
||||
foreach (string file in files)
|
||||
{
|
||||
fileInfo = new FileInfo(file);
|
||||
if (string.IsNullOrEmpty(fileInfo.DirectoryName) || fileInfo.LastWriteTime > dateTime)
|
||||
continue;
|
||||
directorySegments = fileInfo.DirectoryName.Split(Path.DirectorySeparatorChar);
|
||||
if (directorySegments.Length < sourceDirectorySegments.Length)
|
||||
continue;
|
||||
weekOfYear = $"{fileInfo.CreationTime.Year}_Week_{calendar.GetWeekOfYear(fileInfo.CreationTime, CalendarWeekRule.FirstDay, DayOfWeek.Sunday):00}";
|
||||
// checkDirectory = string.Concat(archiveDirectory, Path.DirectorySeparatorChar, weekOfYear, Path.DirectorySeparatorChar, string.Join(Path.DirectorySeparatorChar, directorySegments.Skip(sourceDirectorySegments.Length)));
|
||||
checkDirectory = string.Concat(archiveDirectory, Path.DirectorySeparatorChar, weekOfYear);
|
||||
for (int i = sourceDirectorySegments.Length; i < directorySegments.Length; i++)
|
||||
checkDirectory = string.Concat(checkDirectory, Path.DirectorySeparatorChar, directorySegments[i]);
|
||||
if (!Directory.Exists(checkDirectory))
|
||||
_ = Directory.CreateDirectory(checkDirectory);
|
||||
checkFile = Path.Combine(checkDirectory, fileInfo.Name);
|
||||
if (File.Exists(checkFile))
|
||||
continue;
|
||||
// File.WriteAllText(checkFile, string.Empty);
|
||||
File.Move(fileInfo.FullName, checkFile);
|
||||
}
|
||||
}
|
||||
|
||||
internal static void ArchiveFiles(ILogger<Worker> logger, List<string> args)
|
||||
{
|
||||
string days = args[4];
|
||||
string pattern = args[2];
|
||||
string sourceDirectory = args[0];
|
||||
string archiveDirectory = Path.GetFullPath(args[3]);
|
||||
logger.LogInformation(sourceDirectory);
|
||||
TryArchiveFiles(sourceDirectory, pattern, archiveDirectory, days);
|
||||
}
|
||||
|
||||
}
|
151
Day/2024-Q2/Helper-2024-04-03.cs
Normal file
151
Day/2024-Q2/Helper-2024-04-03.cs
Normal file
@ -0,0 +1,151 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Collections.ObjectModel;
|
||||
|
||||
namespace File_Folder_Helper.Day;
|
||||
|
||||
internal static partial class Helper20240403
|
||||
{
|
||||
|
||||
private record DynamicHostConfigurationProtocolConfiguration(string[] Columns,
|
||||
string Directory,
|
||||
string Ignore,
|
||||
int KeyIndex,
|
||||
string Pattern,
|
||||
string Primary);
|
||||
|
||||
private static string? GetMatch(DynamicHostConfigurationProtocolConfiguration dynamicHostConfigurationProtocolConfiguration, string[] files)
|
||||
{
|
||||
string? result = null;
|
||||
foreach (string file in files)
|
||||
{
|
||||
if (file.EndsWith(dynamicHostConfigurationProtocolConfiguration.Primary))
|
||||
result = file;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static ReadOnlyDictionary<string, int> GetKeyToCounts(DynamicHostConfigurationProtocolConfiguration dynamicHostConfigurationProtocolConfiguration, string[] files)
|
||||
{
|
||||
Dictionary<string, int> results = [];
|
||||
bool check;
|
||||
string key;
|
||||
string[] lines;
|
||||
string[] segments;
|
||||
List<int>? collection;
|
||||
Dictionary<string, List<int>> keyValuePairs = [];
|
||||
int columnsLength = dynamicHostConfigurationProtocolConfiguration.Columns.Length;
|
||||
foreach (string file in files)
|
||||
{
|
||||
check = false;
|
||||
lines = File.ReadAllLines(file);
|
||||
foreach (string line in lines)
|
||||
{
|
||||
if (line.Length < 3 || line[0] != '|' || line[^1] != '|')
|
||||
continue;
|
||||
segments = line.Split('|');
|
||||
if (segments.Length != columnsLength)
|
||||
continue;
|
||||
key = segments[dynamicHostConfigurationProtocolConfiguration.KeyIndex].Trim();
|
||||
if (!check)
|
||||
{
|
||||
if (!key.StartsWith('-') || !key.EndsWith('-'))
|
||||
continue;
|
||||
check = true;
|
||||
continue;
|
||||
}
|
||||
if (key == dynamicHostConfigurationProtocolConfiguration.Ignore)
|
||||
break;
|
||||
if (!keyValuePairs.TryGetValue(key, out collection))
|
||||
{
|
||||
keyValuePairs.Add(key, []);
|
||||
if (!keyValuePairs.TryGetValue(key, out collection))
|
||||
throw new Exception();
|
||||
}
|
||||
collection.Add(1);
|
||||
}
|
||||
}
|
||||
foreach (KeyValuePair<string, List<int>> keyValuePair in keyValuePairs.OrderByDescending(l => l.Value.Count))
|
||||
results.Add(keyValuePair.Key, keyValuePair.Value.Count);
|
||||
return new(results);
|
||||
}
|
||||
|
||||
private static ReadOnlyDictionary<string, ReadOnlyDictionary<string, ReadOnlyCollection<string>>> GetKeyValuePairs(DynamicHostConfigurationProtocolConfiguration dynamicHostConfigurationProtocolConfiguration, string[] files)
|
||||
{
|
||||
ReadOnlyDictionary<string, ReadOnlyDictionary<string, ReadOnlyCollection<string>>> results;
|
||||
bool check;
|
||||
string key;
|
||||
string[] lines;
|
||||
string[] segments;
|
||||
List<string> keys = [];
|
||||
Dictionary<string, ReadOnlyCollection<string>> keyValuePairs;
|
||||
Dictionary<string, ReadOnlyDictionary<string, ReadOnlyCollection<string>>> fileTo = [];
|
||||
int columnsLength = dynamicHostConfigurationProtocolConfiguration.Columns.Length;
|
||||
foreach (string file in files)
|
||||
{
|
||||
keys.Clear();
|
||||
check = false;
|
||||
keyValuePairs = [];
|
||||
lines = File.ReadAllLines(file);
|
||||
foreach (string line in lines)
|
||||
{
|
||||
if (line.Length < 3 || line[0] != '|' || line[^1] != '|')
|
||||
continue;
|
||||
segments = line.Split('|');
|
||||
if (segments.Length != columnsLength)
|
||||
continue;
|
||||
key = segments[dynamicHostConfigurationProtocolConfiguration.KeyIndex].Trim();
|
||||
if (!check)
|
||||
{
|
||||
if (!key.StartsWith('-') || !key.EndsWith('-'))
|
||||
continue;
|
||||
check = true;
|
||||
continue;
|
||||
}
|
||||
if (key == dynamicHostConfigurationProtocolConfiguration.Ignore)
|
||||
break;
|
||||
if (keys.Contains(key))
|
||||
throw new NotSupportedException($"{key}: is a duplicate!");
|
||||
keys.Add(key);
|
||||
keyValuePairs.Add(key, new(segments.Select(l => l.Trim()).ToArray()));
|
||||
}
|
||||
fileTo.Add(Path.GetFullPath(file), new(keyValuePairs));
|
||||
}
|
||||
results = new(fileTo);
|
||||
return results;
|
||||
}
|
||||
|
||||
private static void AlertIfNewDeviceIsConnected(DynamicHostConfigurationProtocolConfiguration dynamicHostConfigurationProtocolConfiguration, ILogger<Worker> logger)
|
||||
{
|
||||
string[] files = Directory.GetFiles(dynamicHostConfigurationProtocolConfiguration.Directory, dynamicHostConfigurationProtocolConfiguration.Pattern, SearchOption.TopDirectoryOnly);
|
||||
string? match = GetMatch(dynamicHostConfigurationProtocolConfiguration, files);
|
||||
if (string.IsNullOrEmpty(match))
|
||||
throw new NotSupportedException($"{dynamicHostConfigurationProtocolConfiguration.Primary} doesn't exist!");
|
||||
ReadOnlyDictionary<string, int> keyToCounts = GetKeyToCounts(dynamicHostConfigurationProtocolConfiguration, files);
|
||||
foreach (KeyValuePair<string, int> keyToCount in keyToCounts)
|
||||
{
|
||||
if (keyToCount.Value < 2)
|
||||
continue;
|
||||
logger.LogInformation("{Key}: {Count}", keyToCount.Key, keyToCount.Value);
|
||||
}
|
||||
ReadOnlyDictionary<string, ReadOnlyDictionary<string, ReadOnlyCollection<string>>> keyValuePairs = GetKeyValuePairs(dynamicHostConfigurationProtocolConfiguration, files);
|
||||
foreach (KeyValuePair<string, ReadOnlyDictionary<string, ReadOnlyCollection<string>>> keyValuePair in keyValuePairs)
|
||||
{
|
||||
if (!keyValuePair.Key.EndsWith(dynamicHostConfigurationProtocolConfiguration.Primary))
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
internal static void AlertIfNewDeviceIsConnected(ILogger<Worker> logger, List<string> args)
|
||||
{
|
||||
string ignore = args[6];
|
||||
string pattern = args[2];
|
||||
string primary = args[3];
|
||||
string keyIndex = args[5];
|
||||
string directory = args[0];
|
||||
logger.LogInformation(directory);
|
||||
string[] columns = args[4].Split('|');
|
||||
DynamicHostConfigurationProtocolConfiguration dynamicHostConfigurationProtocolConfiguration = new(columns, directory, ignore, int.Parse(keyIndex), pattern, primary);
|
||||
AlertIfNewDeviceIsConnected(dynamicHostConfigurationProtocolConfiguration, logger);
|
||||
}
|
||||
|
||||
}
|
96
Day/2024-Q2/Helper-2024-04-04.cs
Normal file
96
Day/2024-Q2/Helper-2024-04-04.cs
Normal file
@ -0,0 +1,96 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace File_Folder_Helper.Day;
|
||||
|
||||
internal static partial class Helper20240404
|
||||
{
|
||||
|
||||
private record MetaData(int DeviceId,
|
||||
string DeviceType,
|
||||
int DeviceNumber,
|
||||
string DescriptionName,
|
||||
string DescriptionTest,
|
||||
string Frequency,
|
||||
string Date);
|
||||
|
||||
private record CommaSeparatedValuesConfiguration(int Columns,
|
||||
string Directory,
|
||||
int TestIndex,
|
||||
int RegularExpressionGroupCount,
|
||||
string RegularExpressionPattern,
|
||||
string SearchPattern);
|
||||
|
||||
private static MetaData? GetMetaData(CommaSeparatedValuesConfiguration commaSeparatedValuesConfiguration, string fileNameWithoutExtension)
|
||||
{
|
||||
MetaData? result;
|
||||
Match match = Regex.Match(fileNameWithoutExtension, commaSeparatedValuesConfiguration.RegularExpressionPattern);
|
||||
if (!match.Success || match.Groups.Count != commaSeparatedValuesConfiguration.RegularExpressionGroupCount)
|
||||
result = null;
|
||||
else
|
||||
{
|
||||
int deviceId = int.Parse(match.Groups["DeviceId"].Value);
|
||||
int deviceNumber = int.Parse(match.Groups["DeviceNumber"].Value);
|
||||
result = new(deviceId,
|
||||
match.Groups["DeviceType"].Value,
|
||||
deviceNumber,
|
||||
match.Groups["DescriptionName"].Value,
|
||||
match.Groups["DescriptionTest"].Value,
|
||||
match.Groups["Frequency"].Value,
|
||||
match.Groups["Date"].Value);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static void ParseCSV(CommaSeparatedValuesConfiguration commaSeparatedValuesConfiguration, ILogger<Worker> logger)
|
||||
{
|
||||
string line;
|
||||
string test;
|
||||
string[] lines;
|
||||
string[] columns;
|
||||
MetaData? metaData;
|
||||
string fileNameWithoutExtension;
|
||||
string[] files = Directory.GetFiles(commaSeparatedValuesConfiguration.Directory, commaSeparatedValuesConfiguration.SearchPattern, SearchOption.TopDirectoryOnly);
|
||||
logger.LogInformation(files.Length.ToString());
|
||||
foreach (string file in files)
|
||||
{
|
||||
fileNameWithoutExtension = Path.GetFileNameWithoutExtension(file);
|
||||
metaData = GetMetaData(commaSeparatedValuesConfiguration, fileNameWithoutExtension);
|
||||
if (metaData is null)
|
||||
continue;
|
||||
lines = File.ReadAllLines(file);
|
||||
if (lines.Length < 2)
|
||||
continue;
|
||||
line = lines[0];
|
||||
columns = line.Split('"');
|
||||
if (columns.Length != commaSeparatedValuesConfiguration.Columns)
|
||||
continue;
|
||||
test = columns[commaSeparatedValuesConfiguration.TestIndex].Trim().Trim('"');
|
||||
if (test.IndexOf(metaData.DescriptionTest, 0, StringComparison.CurrentCultureIgnoreCase) == -1)
|
||||
continue;
|
||||
for (int i = 1; i < lines.Length; i++)
|
||||
{
|
||||
line = lines[i];
|
||||
if (line.Length < 1)
|
||||
continue;
|
||||
columns = line.Split(',').Select(l => l.Trim().Trim('"')).ToArray();
|
||||
if (columns.Length != commaSeparatedValuesConfiguration.Columns)
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal static void ParseCSV(ILogger<Worker> logger, List<string> args)
|
||||
{
|
||||
string directory = args[0];
|
||||
string regularExpressionPattern = args[2];
|
||||
string regularExpressionGroupCount = args[3];
|
||||
string searchPattern = args[4];
|
||||
string columns = args[5];
|
||||
string testIndex = args[6];
|
||||
logger.LogInformation(directory);
|
||||
CommaSeparatedValuesConfiguration commaSeparatedValuesConfiguration = new(int.Parse(columns), directory, int.Parse(testIndex), int.Parse(regularExpressionGroupCount), regularExpressionPattern, searchPattern);
|
||||
ParseCSV(commaSeparatedValuesConfiguration, logger);
|
||||
}
|
||||
|
||||
}
|
91
Day/2024-Q2/Helper-2024-04-09.cs
Normal file
91
Day/2024-Q2/Helper-2024-04-09.cs
Normal file
@ -0,0 +1,91 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace File_Folder_Helper.Day;
|
||||
|
||||
internal static partial class Helper20240409
|
||||
{
|
||||
|
||||
internal record FsSize( // cSpell:disable
|
||||
[property: JsonPropertyName("name")] string Name,
|
||||
[property: JsonPropertyName("object")] string Object,
|
||||
[property: JsonPropertyName("pmon")] string PMon,
|
||||
[property: JsonPropertyName("unit")] string Unit,
|
||||
[property: JsonPropertyName("timeresolution")] string TimeResolution,
|
||||
[property: JsonPropertyName("aggr")] string Aggr,
|
||||
[property: JsonPropertyName("data")] List<double[]> Data
|
||||
); // cSpell:restore
|
||||
|
||||
[JsonSourceGenerationOptions(WriteIndented = true, AllowTrailingCommas = true)]
|
||||
[JsonSerializable(typeof(FsSize))]
|
||||
internal partial class FsSizeSourceGenerationContext : JsonSerializerContext
|
||||
{
|
||||
}
|
||||
|
||||
internal static void MonA(ILogger<Worker> logger, List<string> args)
|
||||
{
|
||||
string url;
|
||||
FsSize? fsSize;
|
||||
string[] segments;
|
||||
Task<string> json;
|
||||
string jsonSection;
|
||||
string urlBase = args[3];
|
||||
string selector = args[6];
|
||||
string urlPartA = args[4];
|
||||
string urlPartC = args[5];
|
||||
string directory = args[0];
|
||||
string aggregation = args[8];
|
||||
int skip = int.Parse(args[7]);
|
||||
string searchPattern = args[2];
|
||||
string fileNameWithoutExtension;
|
||||
string[] ignore = args[9].Split(',');
|
||||
Task<HttpResponseMessage> httpResponseMessage;
|
||||
string[] files = Directory.GetFiles(directory, searchPattern, SearchOption.TopDirectoryOnly);
|
||||
HttpClient httpClient = new(new HttpClientHandler { UseCookies = false }) { BaseAddress = new Uri(urlBase) };
|
||||
logger.LogInformation("{directory} has {files}(s)", directory, files.Length);
|
||||
foreach (string file in files)
|
||||
{
|
||||
fileNameWithoutExtension = Path.GetFileNameWithoutExtension(file);
|
||||
if (ignore.Contains(fileNameWithoutExtension))
|
||||
continue;
|
||||
url = $"{httpClient.BaseAddress}{urlPartA}{fileNameWithoutExtension}{urlPartC}";
|
||||
httpResponseMessage = httpClient.GetAsync(url);
|
||||
httpResponseMessage.Wait();
|
||||
if (!httpResponseMessage.Result.IsSuccessStatusCode)
|
||||
{
|
||||
logger.LogWarning("{StatusCode} for {url}", httpResponseMessage.Result.StatusCode, url);
|
||||
continue;
|
||||
}
|
||||
json = httpResponseMessage.Result.Content.ReadAsStringAsync();
|
||||
json.Wait();
|
||||
if (json.Result.Length < 3)
|
||||
{
|
||||
logger.LogInformation("{Size} | {Julian} | {PMon} | {FileNameWithoutExtension}", -1, -1, "{}", fileNameWithoutExtension);
|
||||
continue;
|
||||
}
|
||||
segments = json.Result.Split($"\"{fileNameWithoutExtension}{selector}");
|
||||
if (segments.Length < 2)
|
||||
{
|
||||
logger.LogInformation("{Size} | {Julian} | {PMon} | {FileNameWithoutExtension}", -1, -1, selector, fileNameWithoutExtension);
|
||||
continue;
|
||||
}
|
||||
for (int i = 1; i < segments.Length; i++)
|
||||
{
|
||||
jsonSection = segments[i][skip..][..^1];
|
||||
fsSize = JsonSerializer.Deserialize(jsonSection, FsSizeSourceGenerationContext.Default.FsSize);
|
||||
if (fsSize is null)
|
||||
continue;
|
||||
if (fsSize.Aggr != aggregation)
|
||||
continue;
|
||||
if (fsSize.Data.Count == 0 || fsSize.Data[0].Length == 0)
|
||||
{
|
||||
logger.LogInformation("{Size} | {Julian} | {PMon} | {FileNameWithoutExtension}", -1, -1, nameof(FsSize.Data), fileNameWithoutExtension);
|
||||
continue;
|
||||
}
|
||||
logger.LogInformation("{Size} | {Julian} | {PMon} | {FileNameWithoutExtension}", fsSize.Data[0][1].ToString().PadLeft(20, '0'), fsSize.Data[0][0], fsSize.PMon, fileNameWithoutExtension);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
62
Day/2024-Q2/Helper-2024-04-17.cs
Normal file
62
Day/2024-Q2/Helper-2024-04-17.cs
Normal file
@ -0,0 +1,62 @@
|
||||
using File_Folder_Helper.Helpers;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Collections.ObjectModel;
|
||||
|
||||
namespace File_Folder_Helper.Day;
|
||||
|
||||
internal static partial class Helper20240417
|
||||
{
|
||||
|
||||
private static void RunCommand(ILogger<Worker> logger, string directory, string commandFileName, List<string> files, int before, CancellationToken cancellationToken)
|
||||
{
|
||||
bool usePathCombine = false;
|
||||
string command = $"npx eclint fix {string.Join(' ', files)}";
|
||||
string output = HelperNPM.RunCommand(commandFileName, command, directory);
|
||||
logger.LogInformation(output);
|
||||
if (output.Contains("error", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
Environment.ExitCode = 2;
|
||||
logger.LogCritical("Setting exit code {ExitCode}", Environment.ExitCode);
|
||||
throw new Exception(output);
|
||||
}
|
||||
ReadOnlyCollection<string> afterGitOthersModifiedAndDeletedExcludingStandardFiles = HelperGit.GetOthersModifiedAndDeletedExcludingStandardFiles(directory, usePathCombine, cancellationToken);
|
||||
int after = afterGitOthersModifiedAndDeletedExcludingStandardFiles.Count;
|
||||
if (before != after)
|
||||
{
|
||||
List<string> fileNames = [];
|
||||
foreach (string file in afterGitOthersModifiedAndDeletedExcludingStandardFiles)
|
||||
{
|
||||
if (file.Contains(' '))
|
||||
continue;
|
||||
if (files.Contains(file))
|
||||
continue;
|
||||
fileNames.Add(Path.GetFileName(file));
|
||||
}
|
||||
Environment.ExitCode = 1;
|
||||
throw new Exception($"Files were modified exiting with exit code {Environment.ExitCode}!{Environment.NewLine}{string.Join(Environment.NewLine, fileNames)}");
|
||||
}
|
||||
}
|
||||
|
||||
internal static void FilteredRunCommand(ILogger<Worker> logger, List<string> args, CancellationToken cancellationToken)
|
||||
{
|
||||
List<string> files = [];
|
||||
string directory = args[0];
|
||||
bool usePathCombine = false;
|
||||
string commandFileName = args[2];
|
||||
ReadOnlyCollection<string> gitOthersModifiedAndDeletedExcludingStandardFiles = HelperGit.GetOthersModifiedAndDeletedExcludingStandardFiles(directory, usePathCombine, cancellationToken);
|
||||
int before = gitOthersModifiedAndDeletedExcludingStandardFiles.Count;
|
||||
foreach (string file in gitOthersModifiedAndDeletedExcludingStandardFiles)
|
||||
{
|
||||
if (file.Contains(' '))
|
||||
{
|
||||
logger.LogInformation("Skipping <{File}>", file);
|
||||
continue;
|
||||
}
|
||||
files.Add(file);
|
||||
}
|
||||
logger.LogInformation("{directory} has {files} file(s)", directory, before);
|
||||
if (files.Count > 0)
|
||||
RunCommand(logger, directory, commandFileName, files, before, cancellationToken);
|
||||
}
|
||||
|
||||
}
|
93
Day/2024-Q2/Helper-2024-04-26.cs
Normal file
93
Day/2024-Q2/Helper-2024-04-26.cs
Normal file
@ -0,0 +1,93 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Text;
|
||||
|
||||
namespace File_Folder_Helper.Day;
|
||||
|
||||
internal static partial class Helper20240426
|
||||
{
|
||||
|
||||
private static void Write(string toA, string toB, string matchA, string matchB, string file, List<string> lines)
|
||||
{
|
||||
StringBuilder stringBuilder = new();
|
||||
foreach (string line in lines)
|
||||
_ = stringBuilder.AppendLine(line.Replace(matchB, toB));
|
||||
string checkFile = file.Replace(matchA, toA);
|
||||
_ = Directory.CreateDirectory(Path.GetDirectoryName(checkFile) ?? throw new NullReferenceException());
|
||||
if (!File.Exists(checkFile))
|
||||
File.WriteAllText(checkFile, stringBuilder.ToString());
|
||||
}
|
||||
|
||||
private static void UpdateTestFiles(ILogger<Worker> logger, string to, string match, string staticDirectoryName, List<string> files)
|
||||
{
|
||||
List<string> lines;
|
||||
string directoryName;
|
||||
string fistLineCheck;
|
||||
string lastLineCheck = "#endif";
|
||||
foreach (string file in files)
|
||||
{
|
||||
directoryName = Path.GetFileName(Path.GetDirectoryName(file) ?? throw new NullReferenceException(nameof(directoryName)));
|
||||
if (directoryName == staticDirectoryName)
|
||||
continue;
|
||||
lines = File.ReadAllLines(file).ToList();
|
||||
if (directoryName == match)
|
||||
Write(to, to.Replace('.', '_'), match, match.Replace('.', '_'), file, lines);
|
||||
if (lines.Count < 3)
|
||||
continue;
|
||||
fistLineCheck = $"#if {directoryName.Replace('.', '_')}";
|
||||
if (lines[0].StartsWith("#if true") || lines[0].StartsWith(fistLineCheck))
|
||||
continue;
|
||||
for (int i = lines.Count - 1; i > 0; i--)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(lines[i]))
|
||||
break;
|
||||
lines.RemoveAt(i);
|
||||
}
|
||||
if (lines[^1].StartsWith(lastLineCheck))
|
||||
continue;
|
||||
if (lines.All(l => string.IsNullOrEmpty(l) || l.StartsWith("//")))
|
||||
continue;
|
||||
lines.Add(lastLineCheck);
|
||||
lines.Insert(0, fistLineCheck);
|
||||
File.WriteAllText(file, string.Join(Environment.NewLine, lines));
|
||||
logger.LogDebug(file);
|
||||
}
|
||||
}
|
||||
|
||||
private static void UpdateProjectTests(ILogger<Worker> logger, string to, string match, string searchPattern, string staticDirectoryName, string extractDirectoryName, string createSelfDescriptionDirectoryName, string sourceCodeDirectory)
|
||||
{
|
||||
List<string> files = [];
|
||||
List<string> knownDirectories = [];
|
||||
knownDirectories.AddRange(Directory.GetDirectories(sourceCodeDirectory, createSelfDescriptionDirectoryName, SearchOption.AllDirectories));
|
||||
knownDirectories.AddRange(Directory.GetDirectories(sourceCodeDirectory, extractDirectoryName, SearchOption.AllDirectories));
|
||||
knownDirectories.AddRange(Directory.GetDirectories(sourceCodeDirectory, staticDirectoryName, SearchOption.AllDirectories));
|
||||
foreach (string knownDirectory in knownDirectories)
|
||||
files.AddRange(Directory.GetFiles(knownDirectory, searchPattern, SearchOption.AllDirectories));
|
||||
logger.LogInformation("{directory} has {files} file(s)", sourceCodeDirectory, files.Count);
|
||||
UpdateTestFiles(logger, to, match, staticDirectoryName, files);
|
||||
}
|
||||
|
||||
internal static void UpdateTests(ILogger<Worker> logger, List<string> args)
|
||||
{
|
||||
string to = args[9];
|
||||
string match = args[8];
|
||||
string searchPattern = args[7];
|
||||
string[] sourceCodeDirectories;
|
||||
string staticDirectoryName = args[6];
|
||||
string extractDirectoryName = args[5];
|
||||
string sourceCodeDirectoryName = args[3];
|
||||
string directory = Path.GetFullPath(args[0]);
|
||||
string createSelfDescriptionDirectoryName = args[4];
|
||||
string systemVolumeInformation = Path.Combine(directory, args[2]);
|
||||
string[] subDirectories = Directory.GetDirectories(directory, "*", SearchOption.TopDirectoryOnly);
|
||||
foreach (string subDirectory in subDirectories)
|
||||
{
|
||||
if (subDirectory == systemVolumeInformation)
|
||||
continue;
|
||||
sourceCodeDirectories = Directory.GetDirectories(subDirectory, sourceCodeDirectoryName, SearchOption.AllDirectories);
|
||||
if (sourceCodeDirectories.Length != 1)
|
||||
continue;
|
||||
UpdateProjectTests(logger, to, match, searchPattern, staticDirectoryName, extractDirectoryName, createSelfDescriptionDirectoryName, sourceCodeDirectories[0]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
145
Day/2024-Q2/Helper-2024-04-27.cs
Normal file
145
Day/2024-Q2/Helper-2024-04-27.cs
Normal file
@ -0,0 +1,145 @@
|
||||
using File_Folder_Helper.Helpers;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace File_Folder_Helper.Day;
|
||||
|
||||
internal static partial class Helper20240427
|
||||
{
|
||||
|
||||
internal record Asset( // cSpell:disable
|
||||
[property: JsonPropertyName("id")] string? Id,
|
||||
[property: JsonPropertyName("deviceAssetId")] string? DeviceAssetId,
|
||||
[property: JsonPropertyName("ownerId")] string? OwnerId,
|
||||
[property: JsonPropertyName("deviceId")] string? DeviceId,
|
||||
[property: JsonPropertyName("type")] string? Type,
|
||||
[property: JsonPropertyName("originalPath")] string? OriginalPath,
|
||||
[property: JsonPropertyName("previewPath")] string? PreviewPath,
|
||||
[property: JsonPropertyName("fileCreatedAt")] DateTime? FileCreatedAt,
|
||||
[property: JsonPropertyName("fileModifiedAt")] DateTime? FileModifiedAt,
|
||||
[property: JsonPropertyName("isFavorite")] bool? IsFavorite,
|
||||
[property: JsonPropertyName("duration")] object? Duration,
|
||||
[property: JsonPropertyName("thumbnailPath")] string? ThumbnailPath,
|
||||
[property: JsonPropertyName("encodedVideoPath")] string? EncodedVideoPath,
|
||||
[property: JsonPropertyName("checksum")] string? Checksum,
|
||||
[property: JsonPropertyName("isVisible")] bool? IsVisible,
|
||||
[property: JsonPropertyName("livePhotoVideoId")] object? LivePhotoVideoId,
|
||||
[property: JsonPropertyName("updatedAt")] DateTime? UpdatedAt,
|
||||
[property: JsonPropertyName("createdAt")] DateTime? CreatedAt,
|
||||
[property: JsonPropertyName("isArchived")] bool? IsArchived,
|
||||
[property: JsonPropertyName("originalFileName")] string? OriginalFileName,
|
||||
[property: JsonPropertyName("sidecarPath")] string? SidecarPath,
|
||||
[property: JsonPropertyName("isReadOnly")] bool? IsReadOnly,
|
||||
[property: JsonPropertyName("thumbhash")] string? Thumbhash,
|
||||
[property: JsonPropertyName("isOffline")] bool? IsOffline,
|
||||
[property: JsonPropertyName("libraryId")] string? LibraryId,
|
||||
[property: JsonPropertyName("isExternal")] bool? IsExternal,
|
||||
[property: JsonPropertyName("deletedAt")] DateTime? DeletedAt,
|
||||
[property: JsonPropertyName("localDateTime")] DateTime? LocalDateTime,
|
||||
[property: JsonPropertyName("stackId")] object? StackId); // cSpell:restore
|
||||
|
||||
[JsonSourceGenerationOptions(WriteIndented = true, AllowTrailingCommas = true)]
|
||||
[JsonSerializable(typeof(List<Asset>))]
|
||||
internal partial class AssetCollectionSourceGenerationContext : JsonSerializerContext
|
||||
{
|
||||
}
|
||||
|
||||
private static string? MoveAsset(string home, string originalFileName, string lastVarDirectoryName, string path)
|
||||
{
|
||||
string? result;
|
||||
string checkFile;
|
||||
string sourceFile;
|
||||
int? match = null;
|
||||
string checkDirectory = home;
|
||||
string sourceDirectory = home;
|
||||
string originalFileNameWithoutExtension = Path.GetFileNameWithoutExtension(originalFileName);
|
||||
List<string> directoryNames = HelperDirectory.GetDirectoryNames(path);
|
||||
for (int i = 0; i < directoryNames.Count; i++)
|
||||
{
|
||||
if (directoryNames[i] != lastVarDirectoryName)
|
||||
continue;
|
||||
match = i;
|
||||
break;
|
||||
}
|
||||
if (match is null)
|
||||
result = null;
|
||||
else
|
||||
{
|
||||
string[] fileNameSegments = directoryNames[^1].Split('-');
|
||||
foreach (string directory in directoryNames.Skip(match.Value + 1).Take(directoryNames.Count - match.Value - 2))
|
||||
sourceDirectory = Path.Combine(sourceDirectory, directory);
|
||||
if (!Directory.Exists(sourceDirectory))
|
||||
result = null;
|
||||
else
|
||||
{
|
||||
sourceFile = Path.Combine(sourceDirectory, directoryNames[^1]);
|
||||
if (!File.Exists(sourceFile))
|
||||
result = null;
|
||||
else
|
||||
{
|
||||
foreach (string directory in directoryNames.Skip(match.Value + 1).Take(directoryNames.Count - match.Value - 2))
|
||||
checkDirectory = Path.Combine(checkDirectory, directory);
|
||||
if (!Directory.Exists(checkDirectory))
|
||||
_ = Directory.CreateDirectory(checkDirectory);
|
||||
checkFile = Path.Combine(checkDirectory, $"{originalFileNameWithoutExtension}{fileNameSegments[^1]}");
|
||||
if (File.Exists(checkFile))
|
||||
result = null;
|
||||
else
|
||||
{
|
||||
File.Move(sourceFile, checkFile);
|
||||
result = checkFile;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static void MoveAssets(ILogger<Worker> logger, string var, string home, string pictures, List<Asset> assets)
|
||||
{
|
||||
string? checkFile;
|
||||
List<string> varDirectoryNames = HelperDirectory.GetDirectoryNames(home);
|
||||
string lastVarDirectoryName = varDirectoryNames[^1];
|
||||
foreach (Asset asset in assets)
|
||||
{
|
||||
if (asset.OriginalFileName is null)
|
||||
continue;
|
||||
if (asset.Type is null or not "IMAGE")
|
||||
continue;
|
||||
if (asset.PreviewPath is null || !asset.PreviewPath.StartsWith(var))
|
||||
continue;
|
||||
if (asset.ThumbnailPath is null || !asset.ThumbnailPath.StartsWith(var))
|
||||
continue;
|
||||
if (asset.OriginalPath is null || !asset.OriginalPath.StartsWith(pictures))
|
||||
continue;
|
||||
checkFile = MoveAsset(home, asset.OriginalFileName, lastVarDirectoryName, asset.PreviewPath);
|
||||
if (checkFile is null)
|
||||
continue;
|
||||
checkFile = MoveAsset(home, asset.OriginalFileName, lastVarDirectoryName, asset.ThumbnailPath);
|
||||
if (checkFile is null)
|
||||
continue;
|
||||
logger.LogDebug("<{OriginalFileName}> moved.", asset.OriginalFileName);
|
||||
}
|
||||
}
|
||||
|
||||
#pragma warning restore IDE0055, IDE0059, IDE0060, IDE2000, CS0168
|
||||
|
||||
internal static void Immich(Models.AppSettings appSettings, ILogger<Worker> logger, List<string> args)
|
||||
{
|
||||
string var = args[5];
|
||||
string home = args[6];
|
||||
string query = args[3];
|
||||
string jsonFile = args[4];
|
||||
string pictures = args[7];
|
||||
string directory = args[0];
|
||||
logger.LogInformation(query);
|
||||
string databasePassword = args[2];
|
||||
string json = File.ReadAllText(Path.Combine(directory, jsonFile));
|
||||
List<Asset> assets = JsonSerializer.Deserialize(json, AssetCollectionSourceGenerationContext.Default.ListAsset) ?? throw new NullReferenceException();
|
||||
string encryptedPassword = RijndaelEncryption.Encrypt(databasePassword, appSettings.Company);
|
||||
MoveAssets(logger, var, home, pictures, assets);
|
||||
logger.LogInformation("Encrypted Password: [{EncryptedPassword}]", encryptedPassword);
|
||||
}
|
||||
|
||||
}
|
56
Day/2024-Q2/Helper-2024-04-29.cs
Normal file
56
Day/2024-Q2/Helper-2024-04-29.cs
Normal file
@ -0,0 +1,56 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace File_Folder_Helper.Day;
|
||||
|
||||
internal static partial class Helper20240429
|
||||
{
|
||||
|
||||
internal static void GitConfigCleanUp(ILogger<Worker> logger, List<string> args)
|
||||
{
|
||||
string[] files;
|
||||
Process? process;
|
||||
string? directory;
|
||||
string standardError;
|
||||
string ignoreError = args[5];
|
||||
string searchPattern = args[3];
|
||||
ProcessStartInfo processStartInfo;
|
||||
string root = Path.GetFullPath(args[0]);
|
||||
string[] removeRemotes = args[4].Split(',');
|
||||
string systemVolumeInformation = Path.Combine(root, args[2]);
|
||||
string[] subDirectories = Directory.GetDirectories(root, "*", SearchOption.TopDirectoryOnly);
|
||||
foreach (string subDirectory in subDirectories)
|
||||
{
|
||||
if (subDirectory == systemVolumeInformation)
|
||||
continue;
|
||||
files = Directory.GetFiles(subDirectory, searchPattern, SearchOption.AllDirectories);
|
||||
foreach (string file in files)
|
||||
{
|
||||
directory = Path.GetDirectoryName(file);
|
||||
if (directory is null)
|
||||
continue;
|
||||
foreach (string removeRemote in removeRemotes)
|
||||
{
|
||||
processStartInfo = new()
|
||||
{
|
||||
FileName = "git",
|
||||
WorkingDirectory = directory,
|
||||
Arguments = $"remote rm {removeRemote}",
|
||||
RedirectStandardError = true
|
||||
};
|
||||
process = Process.Start(processStartInfo);
|
||||
if (process is null)
|
||||
continue;
|
||||
#pragma warning disable IDE0058
|
||||
process.WaitForExit(7000);
|
||||
#pragma warning restore IDE0058
|
||||
standardError = process.StandardError.ReadToEnd();
|
||||
if (!standardError.Contains(ignoreError))
|
||||
logger.LogInformation(standardError);
|
||||
logger.LogInformation("for <{directoryName}> remote rm {removeRemote}", directory, removeRemote);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -6,7 +6,7 @@ namespace File_Folder_Helper.Helpers;
|
||||
internal static class HelperDay
|
||||
{
|
||||
|
||||
internal static void Select(AppSettings appSettings, ILogger<Worker> logger, List<string> args)
|
||||
internal static void Select(AppSettings appSettings, ILogger<Worker> logger, List<string> args, CancellationToken cancellationToken)
|
||||
{
|
||||
if (args[1] == "Day-Helper-2023-09-06")
|
||||
Day.Helper20230906.SaveJson(logger, args[0]);
|
||||
@ -29,7 +29,7 @@ internal static class HelperDay
|
||||
else if (args[1] == "Day-Helper-2023-12-05")
|
||||
Day.Helper20231205.SplitMarkdownFile(logger, args);
|
||||
else if (args[1] == "Day-Helper-2023-12-12")
|
||||
Day.Helper20231212.SplitJsonFile(logger, args);
|
||||
logger.LogError("{arg} - was deleted on 2024-04-08", args[1]);
|
||||
else if (args[1] == "Day-Helper-2023-12-22")
|
||||
Day.Helper20231222.ConvertId(logger, args);
|
||||
else if (args[1] == "Day-Helper-2024-01-05")
|
||||
@ -39,7 +39,27 @@ internal static class HelperDay
|
||||
else if (args[1] == "Day-Helper-2024-01-07")
|
||||
Day.Helper20240107.DirectoryToISO(logger, args);
|
||||
else if (args[1] == "Day-Helper-2024-01-08")
|
||||
Day.Helper20240108.SortCodeMethods(logger, args);
|
||||
Day.Helper20240108.SortCodeMethods(logger, args, cancellationToken);
|
||||
else if (args[1] == "Day-Helper-2024-01-27")
|
||||
logger.LogError("{arg} - has been migrated to Clipboard_Send_Keys", args[1]);
|
||||
else if (args[1] == "Day-Helper-2024-01-29")
|
||||
Day.Helper20240129.JsonToTsv(logger, args);
|
||||
else if (args[1] == "Day-Helper-2024-03-05")
|
||||
Day.Helper20240305.ArchiveFiles(logger, args);
|
||||
else if (args[1] == "Day-Helper-2024-04-03")
|
||||
Day.Helper20240403.AlertIfNewDeviceIsConnected(logger, args);
|
||||
else if (args[1] == "Day-Helper-2024-04-04")
|
||||
Day.Helper20240404.ParseCSV(logger, args);
|
||||
else if (args[1] == "Day-Helper-2024-04-09")
|
||||
Day.Helper20240409.MonA(logger, args);
|
||||
else if (args[1] == "Day-Helper-2024-04-17")
|
||||
Day.Helper20240417.FilteredRunCommand(logger, args, cancellationToken);
|
||||
else if (args[1] == "Day-Helper-2024-04-26")
|
||||
Day.Helper20240426.UpdateTests(logger, args);
|
||||
else if (args[1] == "Day-Helper-2024-04-27")
|
||||
Day.Helper20240427.Immich(appSettings, logger, args);
|
||||
else if (args[1] == "Day-Helper-2024-04-29")
|
||||
Day.Helper20240429.GitConfigCleanUp(logger, args);
|
||||
else
|
||||
throw new Exception(appSettings.Company);
|
||||
}
|
||||
|
@ -1,18 +1,24 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<OutputType>Exe</OutputType>
|
||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<UserSecretsId>eb9e8f58-fcb5-45bb-9d4d-54f064c485b1</UserSecretsId>
|
||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
|
||||
<UserSecretsId>8da397d4-13ec-4576-9722-3c79cad25563</UserSecretsId>
|
||||
<UserSecretsIdWindowsShortcut>eb9e8f58-fcb5-45bb-9d4d-54f064c485b1</UserSecretsIdWindowsShortcut>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<RuntimeHostConfigurationOption Include="AssemblyName" Value="File-Folder-Helper" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="DiscUtils.Iso9660" Version="0.16.13" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="8.0.0" />
|
||||
<PackageReference Include="runtime.win-x64.Microsoft.DotNet.ILCompiler" Version="8.0.0" />
|
||||
<PackageReference Include="System.Text.Json" Version="8.0.0" />
|
||||
<PackageReference Include="runtime.win-x64.Microsoft.DotNet.ILCompiler" Version="8.0.4" />
|
||||
<PackageReference Include="System.Text.Json" Version="8.0.3" />
|
||||
<PackageReference Include="TextCopy" Version="6.2.1" />
|
||||
<PackageReference Include="WindowsShortcutFactory" Version="1.1.0" />
|
||||
</ItemGroup>
|
||||
</Project>
|
42
Helpers/HelperDirectory.cs
Normal file
42
Helpers/HelperDirectory.cs
Normal file
@ -0,0 +1,42 @@
|
||||
namespace File_Folder_Helper.Helpers;
|
||||
|
||||
internal static class HelperDirectory
|
||||
{
|
||||
|
||||
internal static List<string> GetDirectoryNames(string directory)
|
||||
{
|
||||
List<string> results = [];
|
||||
string? fileName;
|
||||
string? checkDirectory = directory;
|
||||
string? pathRoot = Path.GetPathRoot(directory);
|
||||
string extension = Path.GetExtension(directory);
|
||||
if (string.IsNullOrEmpty(pathRoot))
|
||||
throw new NullReferenceException(nameof(pathRoot));
|
||||
if (Directory.Exists(directory))
|
||||
{
|
||||
fileName = Path.GetFileName(directory);
|
||||
if (!string.IsNullOrEmpty(fileName))
|
||||
results.Add(fileName);
|
||||
}
|
||||
else if ((string.IsNullOrEmpty(extension) || extension.Length > 3) && !File.Exists(directory))
|
||||
{
|
||||
fileName = Path.GetFileName(directory);
|
||||
if (!string.IsNullOrEmpty(fileName))
|
||||
results.Add(fileName);
|
||||
}
|
||||
for (int i = 0; i < int.MaxValue; i++)
|
||||
{
|
||||
checkDirectory = Path.GetDirectoryName(checkDirectory);
|
||||
if (string.IsNullOrEmpty(checkDirectory) || checkDirectory == pathRoot)
|
||||
break;
|
||||
fileName = Path.GetFileName(checkDirectory);
|
||||
if (string.IsNullOrEmpty(fileName))
|
||||
continue;
|
||||
results.Add(fileName);
|
||||
}
|
||||
results.Add(pathRoot);
|
||||
results.Reverse();
|
||||
return results;
|
||||
}
|
||||
|
||||
}
|
66
Helpers/HelperGit.cs
Normal file
66
Helpers/HelperGit.cs
Normal file
@ -0,0 +1,66 @@
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Diagnostics;
|
||||
using System.Text;
|
||||
|
||||
namespace File_Folder_Helper.Helpers;
|
||||
|
||||
internal static class HelperGit
|
||||
{
|
||||
|
||||
private record ProcessResult(string Errors,
|
||||
int ExitCode,
|
||||
string Output);
|
||||
|
||||
private static async Task<ProcessResult> RunProcessAsync(string application, string arguments, string workingDirectory, CancellationToken cancellationToken)
|
||||
{
|
||||
using Process process = new();
|
||||
StringBuilder outputBuilder = new();
|
||||
StringBuilder errorsBuilder = new();
|
||||
process.StartInfo = new ProcessStartInfo
|
||||
{
|
||||
CreateNoWindow = true,
|
||||
UseShellExecute = false,
|
||||
RedirectStandardError = true,
|
||||
RedirectStandardOutput = true,
|
||||
FileName = application,
|
||||
Arguments = arguments,
|
||||
WorkingDirectory = workingDirectory,
|
||||
};
|
||||
process.OutputDataReceived += (_, args) => outputBuilder.AppendLine(args.Data);
|
||||
process.ErrorDataReceived += (_, args) => errorsBuilder.AppendLine(args.Data);
|
||||
_ = process.Start();
|
||||
process.BeginErrorReadLine();
|
||||
process.BeginOutputReadLine();
|
||||
await process.WaitForExitAsync(cancellationToken);
|
||||
return new(errorsBuilder.ToString().Trim(), process.ExitCode, outputBuilder.ToString().Trim());
|
||||
}
|
||||
|
||||
private static async Task<string> RunAsync(string arguments, string workingDirectory, CancellationToken cancellationToken)
|
||||
{
|
||||
ProcessResult result = await RunProcessAsync("git", arguments, workingDirectory, cancellationToken);
|
||||
if (result.ExitCode != 0)
|
||||
throw new Exception($"{result.ExitCode} {result.Errors}");
|
||||
return result.Output;
|
||||
}
|
||||
|
||||
internal static ReadOnlyCollection<string> GetOthersModifiedAndDeletedExcludingStandardFiles(string repositoryDirectory, bool usePathCombine, CancellationToken cancellationToken)
|
||||
{
|
||||
List<string> results = [];
|
||||
string checkDirectory = Path.Combine(repositoryDirectory, ".git");
|
||||
if (Directory.Exists(checkDirectory))
|
||||
{
|
||||
Task<string> task = RunAsync($"ls-files --others --modified --deleted --exclude-standard", repositoryDirectory, cancellationToken);
|
||||
task.Wait(cancellationToken);
|
||||
string[] files = task.Result.Split("\r\n");
|
||||
foreach (string file in files)
|
||||
{
|
||||
if (!usePathCombine)
|
||||
results.Add(file);
|
||||
else
|
||||
results.Add(Path.GetFullPath(Path.Combine(repositoryDirectory, file)));
|
||||
}
|
||||
}
|
||||
return new(results);
|
||||
}
|
||||
|
||||
}
|
@ -1,84 +0,0 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Globalization;
|
||||
|
||||
namespace File_Folder_Helper.Helpers;
|
||||
|
||||
internal static class HelperHardcodedFileSearchAndSort
|
||||
{
|
||||
|
||||
internal static void HardcodedFileSearchAndSort(ILogger log, string sourceDirectory, SearchOption searchOption = SearchOption.TopDirectoryOnly)
|
||||
{
|
||||
bool check;
|
||||
string lines;
|
||||
string checkFile;
|
||||
string? directory;
|
||||
FileInfo fileInfo;
|
||||
string weekOfYear;
|
||||
string checkDirectory;
|
||||
CultureInfo cultureInfo = new("en-US");
|
||||
Calendar calendar = cultureInfo.Calendar;
|
||||
string[] hardcodedValues =
|
||||
[
|
||||
"BIORAD2",
|
||||
"BIORAD3",
|
||||
"BIORAD4",
|
||||
"BIORAD5",
|
||||
"CDE2",
|
||||
"CDE3",
|
||||
"CDE4",
|
||||
"CDE5",
|
||||
"CDE6",
|
||||
"HGCV1",
|
||||
"HGCV2",
|
||||
"HGCV3",
|
||||
"TENCOR1",
|
||||
"TENCOR2",
|
||||
"TENCOR3",
|
||||
"SP101",
|
||||
"SPV01",
|
||||
"SRP",
|
||||
"WC6Inch",
|
||||
"WC8Inch",
|
||||
"Bio-Rad"
|
||||
];
|
||||
string[] files = Directory.GetFiles(sourceDirectory, "*", searchOption);
|
||||
foreach (string file in files)
|
||||
{
|
||||
directory = Path.GetDirectoryName(file);
|
||||
if (string.IsNullOrEmpty(directory))
|
||||
continue;
|
||||
check = false;
|
||||
fileInfo = new(file);
|
||||
weekOfYear = calendar.GetWeekOfYear(fileInfo.LastWriteTime, CalendarWeekRule.FirstDay, DayOfWeek.Sunday).ToString("00");
|
||||
for (int i = 1; i < 3; i++)
|
||||
{
|
||||
if (check)
|
||||
break;
|
||||
lines = i switch
|
||||
{
|
||||
1 => fileInfo.Name,
|
||||
2 => File.ReadAllText(file),
|
||||
_ => throw new NotImplementedException()
|
||||
};
|
||||
foreach (string hardcodedValue in hardcodedValues)
|
||||
{
|
||||
if (!lines.Contains(hardcodedValue))
|
||||
continue;
|
||||
checkDirectory = Path.Combine(directory, $"{fileInfo.LastWriteTime:yyyy}_Week_{weekOfYear}", fileInfo.LastWriteTime.ToString("yyyy-MM-dd"), hardcodedValue);
|
||||
if (!Directory.Exists(checkDirectory))
|
||||
_ = Directory.CreateDirectory(checkDirectory);
|
||||
checkFile = Path.Combine(checkDirectory, Path.GetFileName(file));
|
||||
if (File.Exists(checkFile) || !File.Exists(file))
|
||||
continue;
|
||||
try
|
||||
{ File.Move(file, checkFile); }
|
||||
catch (Exception) { }
|
||||
check = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
log.LogInformation("{sourceDirectory}", sourceDirectory);
|
||||
}
|
||||
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
using File_Folder_Helper.Models;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
@ -14,6 +15,11 @@ internal static partial class HelperKanbanMetadata
|
||||
[GeneratedRegex("[\\s!?.,@:;|\\\\/\"'`£$%\\^&*{}[\\]()<>~#+\\-=_¬]+")]
|
||||
private static partial Regex InvalidCharacter();
|
||||
|
||||
private record Record(FileInfo FileInfo,
|
||||
string Group,
|
||||
int GroupCount,
|
||||
int ItemLineNumber);
|
||||
|
||||
private static string GetParamCase(string value)
|
||||
{
|
||||
string result;
|
||||
@ -64,15 +70,15 @@ internal static partial class HelperKanbanMetadata
|
||||
throw new Exception("я надеюсь, что это сработает");
|
||||
}
|
||||
|
||||
private static List<(int, int, string, FileInfo)> GetCollectionFromIndex(string sourceDirectory, string[] lines)
|
||||
private static List<Record> GetCollectionFromIndex(string sourceDirectory, ReadOnlyCollection<string> lines)
|
||||
{
|
||||
List<(int, int, string, FileInfo)> results = [];
|
||||
List<Record> results = [];
|
||||
string line;
|
||||
FileInfo fileInfo;
|
||||
string[] segments;
|
||||
int groupCount = 0;
|
||||
string? group = null;
|
||||
for (int i = 0; i < lines.Length; i++)
|
||||
for (int i = 0; i < lines.Count; i++)
|
||||
{
|
||||
line = lines[i];
|
||||
if (line.Length < 4)
|
||||
@ -91,12 +97,30 @@ internal static partial class HelperKanbanMetadata
|
||||
fileInfo = new(Path.Combine(sourceDirectory, segments[1][..^1]));
|
||||
if (!fileInfo.Exists)
|
||||
continue;
|
||||
results.Add((groupCount, i, group, fileInfo));
|
||||
results.Add(new(fileInfo, group, groupCount, i));
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
internal static void SetMetadata(ILogger log, AppSettings appSettings, string sourceDirectory, bool addTicks)
|
||||
private static void WriteKanbanBoardFile(string fullPath, List<Record> records, string h1)
|
||||
{
|
||||
string? last = null;
|
||||
List<string> lines = [h1, string.Empty];
|
||||
foreach (Record record in records)
|
||||
{
|
||||
if (last is null || record.Group != last)
|
||||
{
|
||||
lines.Add(string.Empty);
|
||||
lines.Add($"## {record.Group}");
|
||||
lines.Add(string.Empty);
|
||||
}
|
||||
lines.Add($"- [ ] {Path.GetFileNameWithoutExtension(record.FileInfo.Name)}");
|
||||
last = record.Group;
|
||||
}
|
||||
File.WriteAllLines(Path.Combine(fullPath, "index.knb.md"), lines);
|
||||
}
|
||||
|
||||
internal static void SetMetadata(ILogger log, AppSettings appSettings, string sourceDirectory)
|
||||
{
|
||||
bool? match;
|
||||
string? paramCase;
|
||||
@ -112,20 +136,22 @@ internal static partial class HelperKanbanMetadata
|
||||
string indexFile = Path.Combine(fullPath, "index.md");
|
||||
if (File.Exists(indexFile))
|
||||
{
|
||||
string[] indexFileLines = File.ReadAllLines(indexFile);
|
||||
List<(int, int, string, FileInfo)> collectionFromIndex = GetCollectionFromIndex(sourceDirectory, indexFileLines);
|
||||
foreach ((int groupCount, int itemLineNumber, string group, FileInfo fileInfo) in collectionFromIndex)
|
||||
FileInfo fileInfo = new(indexFile);
|
||||
(lines, lineNumber) = HelperMarkdown.GetStatusAndFrontMatterYamlEndLineNumbers(fileInfo);
|
||||
ReadOnlyCollection<string> indexFileLines = new(lines);
|
||||
List<Record> records = GetCollectionFromIndex(sourceDirectory, indexFileLines);
|
||||
if (lineNumber.H1 is not null)
|
||||
WriteKanbanBoardFile(fullPath, records, indexFileLines[lineNumber.H1.Value]);
|
||||
foreach (Record record in records)
|
||||
{
|
||||
if (itemLineNumber == 0)
|
||||
if (record.ItemLineNumber == 0)
|
||||
throw new NotSupportedException();
|
||||
(lines, lineNumber) = HelperMarkdown.GetStatusAndFrontMatterYamlEndLineNumbers(fileInfo);
|
||||
(lines, lineNumber) = HelperMarkdown.GetStatusAndFrontMatterYamlEndLineNumbers(record.FileInfo);
|
||||
if (lines.Count == 0)
|
||||
continue;
|
||||
statusLine = $"status: \"{groupCount}-{group}\"";
|
||||
statusLine = $"status: \"{record.GroupCount}-{record.Group}\"";
|
||||
paramCase = lineNumber.H1 is null ? null : GetParamCase(lines[lineNumber.H1.Value]);
|
||||
if (addTicks)
|
||||
indexFileLines[itemLineNumber] = $"{fileInfo.LastWriteTime.Ticks}~~~{indexFileLines[itemLineNumber]}";
|
||||
match = lineNumber.H1 is null || paramCase is null ? null : Path.GetFileNameWithoutExtension(fileInfo.Name) == paramCase;
|
||||
match = lineNumber.H1 is null || paramCase is null ? null : Path.GetFileNameWithoutExtension(record.FileInfo.Name) == paramCase;
|
||||
if (lineNumber.FrontMatterYamlEnd is null)
|
||||
throw new NotSupportedException($"{nameof(SetMetadata)} must be executed first!");
|
||||
if (lineNumber.H1 is not null && paramCase is not null && match is not null && !match.Value)
|
||||
@ -138,10 +164,8 @@ internal static partial class HelperKanbanMetadata
|
||||
continue;
|
||||
lines[lineNumber.Status.Value] = statusLine;
|
||||
}
|
||||
File.WriteAllLines(fileInfo.FullName, lines);
|
||||
File.WriteAllLines(record.FileInfo.FullName, lines);
|
||||
}
|
||||
if (addTicks)
|
||||
File.WriteAllLines(indexFile, indexFileLines);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
using File_Folder_Helper.Models;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
@ -11,6 +12,44 @@ namespace File_Folder_Helper.Helpers;
|
||||
internal static partial class HelperMarkdown
|
||||
{
|
||||
|
||||
private record Input(string? Destination,
|
||||
string Source,
|
||||
string? StartAt);
|
||||
|
||||
private record Record(string Directory,
|
||||
string File,
|
||||
string[] Lines);
|
||||
|
||||
private record MarkdownFile(DateTime CreationDateTime,
|
||||
string Directory,
|
||||
string Extension,
|
||||
string File,
|
||||
string FileName,
|
||||
string FileNameWithoutExtension,
|
||||
string H1,
|
||||
bool IsKanbanIndex,
|
||||
DateTime LastWriteDateTime,
|
||||
LineNumber LineNumber,
|
||||
string Type);
|
||||
|
||||
private record MarkdownFileAndLines(MarkdownFile MarkdownFile,
|
||||
string[] Lines);
|
||||
|
||||
private record MarkdownExtra(ReadOnlyCollection<string>? Assignees,
|
||||
string? Effort,
|
||||
ReadOnlyCollection<H2HexColor>? H2HexColorCollection,
|
||||
ReadOnlyCollection<H2NoCheckboxes>? H2NoCheckboxesCollection,
|
||||
ReadOnlyCollection<H2WithCheckboxes>? H2WithCheckboxesCollection,
|
||||
string? RequestedDateTime);
|
||||
|
||||
private record MarkdownFileH1AndRelativePath(MarkdownFile? MarkdownFile, string[]? Lines, string? H1, string? RelativePath);
|
||||
|
||||
[JsonSourceGenerationOptions(WriteIndented = true, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
[JsonSerializable(typeof(Dictionary<string, JsonElement>))]
|
||||
internal partial class DictionaryStringAndJsonElementSourceGenerationContext : JsonSerializerContext
|
||||
{
|
||||
}
|
||||
|
||||
private static void SetRecursiveLines(AppSettings appSettings, ILogger<Worker> logger, ReadOnlyDictionary<string, List<MarkdownFileAndLines>> keyValuePairs, string linkTitle, MarkdownFile markdownFile, string[] lines, List<char> indentations, List<string> recursiveLines)
|
||||
{
|
||||
if (recursiveLines is null)
|
||||
@ -553,6 +592,7 @@ internal static partial class HelperMarkdown
|
||||
string key;
|
||||
string type;
|
||||
FileInfo fileInfo;
|
||||
bool isKanbanIndex;
|
||||
List<string> lines;
|
||||
LineNumber lineNumber;
|
||||
MarkdownFile markdownFile;
|
||||
@ -574,6 +614,7 @@ internal static partial class HelperMarkdown
|
||||
File.WriteAllLines(file, ["---", $"type: \"{type}\"", "---", string.Empty, $"# {h1}"]);
|
||||
lines = File.ReadAllLines(file).ToList();
|
||||
}
|
||||
isKanbanIndex = fileNameWithoutExtension == "index" && type == "Kanban";
|
||||
markdownFile = new(fileInfo.CreationTime,
|
||||
fileInfo.DirectoryName,
|
||||
fileInfo.Extension,
|
||||
@ -581,6 +622,7 @@ internal static partial class HelperMarkdown
|
||||
fileInfo.Name,
|
||||
fileNameWithoutExtension,
|
||||
h1,
|
||||
isKanbanIndex,
|
||||
fileInfo.LastWriteTime,
|
||||
lineNumber,
|
||||
type);
|
||||
@ -613,7 +655,7 @@ internal static partial class HelperMarkdown
|
||||
continue;
|
||||
lines = relativeTo.Value.Lines;
|
||||
markdownFile = relativeTo.Value.MarkdownFile;
|
||||
if (markdownFile.FileNameWithoutExtension != "index" || markdownFile.Type != "Kanban")
|
||||
if (markdownFile.IsKanbanIndex)
|
||||
continue;
|
||||
if (!File.Exists(markdownFile.File))
|
||||
continue;
|
||||
@ -642,7 +684,7 @@ internal static partial class HelperMarkdown
|
||||
continue;
|
||||
key = Path.GetRelativePath(input.Source, Path.Combine(markdownFile.Directory, segmentsA[1][..^1]));
|
||||
if (!allKeys.Remove(key))
|
||||
throw new NotSupportedException();
|
||||
continue;
|
||||
if (!relativeToCollection.TryGetValue(key, out markdownFileAndLines))
|
||||
continue;
|
||||
markdownExtra = GetMarkdownExtra(markdownFileAndLines);
|
||||
@ -765,6 +807,7 @@ internal static partial class HelperMarkdown
|
||||
Input result;
|
||||
string? startAt = null;
|
||||
string? destination = null;
|
||||
string source = Path.GetFullPath(args[0]);
|
||||
for (int i = 1; i < args.Count; i++)
|
||||
{
|
||||
if (args[i].Length == 2 && i + 1 < args.Count)
|
||||
@ -778,6 +821,8 @@ internal static partial class HelperMarkdown
|
||||
}
|
||||
if (startAt is not null && !Directory.Exists(startAt))
|
||||
throw new Exception($"Start at directory <{startAt}> doesn't exist!");
|
||||
if (startAt is not null && startAt.Length < source.Length)
|
||||
throw new Exception($"Start at directory <{startAt}> must be a subdirectory!");
|
||||
if (destination is not null)
|
||||
{
|
||||
string? root = Path.GetPathRoot(destination);
|
||||
@ -786,7 +831,7 @@ internal static partial class HelperMarkdown
|
||||
if (!Directory.Exists(destination))
|
||||
_ = Directory.CreateDirectory(destination);
|
||||
}
|
||||
result = new(Path.GetFullPath(args[0]), startAt, destination);
|
||||
result = new(destination, source, startAt);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -1019,7 +1064,7 @@ internal static partial class HelperMarkdown
|
||||
continue;
|
||||
lines = relativeTo.Value.Lines;
|
||||
markdownFile = relativeTo.Value.MarkdownFile;
|
||||
if (markdownFile.FileNameWithoutExtension == "index" && markdownFile.Directory.EndsWith(".kanbn"))
|
||||
if (markdownFile.IsKanbanIndex)
|
||||
continue;
|
||||
if (!File.Exists(markdownFile.File))
|
||||
continue;
|
||||
@ -1064,7 +1109,7 @@ internal static partial class HelperMarkdown
|
||||
continue;
|
||||
File.Move(file, checkName);
|
||||
}
|
||||
else if (fileName != fileName.ToLower())
|
||||
else if (!fileName.Equals(fileName, StringComparison.CurrentCultureIgnoreCase))
|
||||
{
|
||||
if (file != checkName)
|
||||
{
|
||||
@ -1138,134 +1183,21 @@ internal static partial class HelperMarkdown
|
||||
if (string.IsNullOrEmpty(input.StartAt) || string.IsNullOrEmpty(input.Destination))
|
||||
throw new NotSupportedException();
|
||||
ReadOnlyDictionary<string, List<Card>> columnsToCards;
|
||||
string jsonFile = Path.Combine(input.Destination, $"{nameof(columnsToCards)}.json");
|
||||
if (File.Exists(jsonFile))
|
||||
File.Delete(jsonFile);
|
||||
columnsToCards = GetColumnsToCards(input, relativeToCollection);
|
||||
if (columnsToCards.Count == 0)
|
||||
File.WriteAllText(jsonFile, "{}");
|
||||
else
|
||||
int kanbanIndexFiles = (from l in relativeToCollection where l.Value.MarkdownFile.IsKanbanIndex select 1).Sum();
|
||||
if (kanbanIndexFiles == 1)
|
||||
{
|
||||
string json = JsonSerializer.Serialize(columnsToCards, ColumnsAndCardsSourceGenerationContext.Default.ReadOnlyDictionaryStringListCard);
|
||||
File.WriteAllText(jsonFile, json);
|
||||
}
|
||||
}
|
||||
|
||||
private static List<Record> GetWithLinksForHugo(AppSettings appSettings, Input input)
|
||||
{
|
||||
List<Record> results = [];
|
||||
string file;
|
||||
string line;
|
||||
string[] lines;
|
||||
string fileName;
|
||||
string? directory;
|
||||
string[] segmentsA;
|
||||
string[] segmentsB;
|
||||
string relativeFile;
|
||||
string segmentsALast;
|
||||
string segmentsBFirst;
|
||||
MarkdownFile markdownFile;
|
||||
int sourceDirectoryLength = input.Source.Length;
|
||||
ReadOnlyDictionary<string, MarkdownFileAndLines> relativeToCollection = GetRelativeToCollection(appSettings, input);
|
||||
foreach (KeyValuePair<string, MarkdownFileAndLines> relativeTo in relativeToCollection)
|
||||
{
|
||||
if (relativeTo.Value.Lines.Length == 0)
|
||||
continue;
|
||||
lines = relativeTo.Value.Lines;
|
||||
markdownFile = relativeTo.Value.MarkdownFile;
|
||||
if (input.Destination is null)
|
||||
continue;
|
||||
if (markdownFile.File.Length < sourceDirectoryLength)
|
||||
continue;
|
||||
if (!File.Exists(markdownFile.File))
|
||||
continue;
|
||||
fileName = $"{input.Destination}{markdownFile.File[sourceDirectoryLength..]}";
|
||||
directory = Path.GetDirectoryName(fileName);
|
||||
if (string.IsNullOrEmpty(directory))
|
||||
continue;
|
||||
for (int i = 0; i < lines.Length; i++)
|
||||
string jsonFile = Path.Combine(input.Destination, $"{nameof(columnsToCards)}.json");
|
||||
if (File.Exists(jsonFile))
|
||||
File.Delete(jsonFile);
|
||||
columnsToCards = GetColumnsToCards(input, relativeToCollection);
|
||||
if (columnsToCards.Count == 0)
|
||||
File.WriteAllText(jsonFile, "{}");
|
||||
else
|
||||
{
|
||||
segmentsA = lines[i].Split("](");
|
||||
if (segmentsA.Length != 2)
|
||||
continue;
|
||||
segmentsALast = segmentsA[^1];
|
||||
if (appSettings.ExcludeSchemes.Any(l => segmentsALast.StartsWith(l)))
|
||||
continue;
|
||||
segmentsB = segmentsALast.Split(")");
|
||||
if (segmentsB.Length != 2)
|
||||
continue;
|
||||
segmentsBFirst = segmentsB[0];
|
||||
if (!segmentsBFirst.EndsWith(".md"))
|
||||
file = Path.GetFullPath(Path.Combine(markdownFile.Directory, segmentsBFirst));
|
||||
else
|
||||
file = Path.GetFullPath(Path.Combine(markdownFile.Directory, segmentsBFirst[..^3]));
|
||||
relativeFile = Path.GetRelativePath(input.Source, file).Replace('\\', '/');
|
||||
line = $"{segmentsA[0]}]({relativeFile}){segmentsB[^1]}";
|
||||
if (lines[i] == line)
|
||||
throw new NotSupportedException($"Line {i} shouldn't match with {line}");
|
||||
lines[i] = line;
|
||||
string json = JsonSerializer.Serialize(columnsToCards, ColumnsAndCardsSourceGenerationContext.Default.ReadOnlyDictionaryStringListCard);
|
||||
File.WriteAllText(jsonFile, json);
|
||||
}
|
||||
results.Add(new(directory, fileName, lines));
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
private static List<string> GetDistinct(List<Record> collection)
|
||||
{
|
||||
List<string> results = [];
|
||||
foreach (Record record in collection)
|
||||
{
|
||||
if (results.Contains(record.Directory))
|
||||
continue;
|
||||
results.Add(record.Directory);
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
private static void CreateMissingDirectories(List<string> directories)
|
||||
{
|
||||
foreach (string directory in directories)
|
||||
{
|
||||
if (!Directory.Exists(directory))
|
||||
_ = Directory.CreateDirectory(directory);
|
||||
}
|
||||
}
|
||||
|
||||
private record Input(string Source,
|
||||
string? StartAt,
|
||||
string? Destination);
|
||||
|
||||
private record Record(string Directory,
|
||||
string File,
|
||||
string[] Lines);
|
||||
|
||||
private record MarkdownFile(DateTime CreationDateTime,
|
||||
string Directory,
|
||||
string Extension,
|
||||
string File,
|
||||
string FileName,
|
||||
string FileNameWithoutExtension,
|
||||
string H1,
|
||||
DateTime LastWriteDateTime,
|
||||
LineNumber LineNumber,
|
||||
string Type);
|
||||
|
||||
private record MarkdownFileAndLines(MarkdownFile MarkdownFile,
|
||||
string[] Lines);
|
||||
|
||||
private record MarkdownExtra(ReadOnlyCollection<string>? Assignees,
|
||||
string? Effort,
|
||||
ReadOnlyCollection<H2HexColor>? H2HexColorCollection,
|
||||
ReadOnlyCollection<H2NoCheckboxes>? H2NoCheckboxesCollection,
|
||||
ReadOnlyCollection<H2WithCheckboxes>? H2WithCheckboxesCollection,
|
||||
string? RequestedDateTime);
|
||||
|
||||
private record MarkdownFileH1AndRelativePath(MarkdownFile? MarkdownFile, string[]? Lines, string? H1, string? RelativePath);
|
||||
|
||||
[JsonSourceGenerationOptions(WriteIndented = true, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
[JsonSerializable(typeof(Dictionary<string, JsonElement>))]
|
||||
internal partial class DictionaryStringAndJsonElementSourceGenerationContext : JsonSerializerContext
|
||||
{
|
||||
}
|
||||
|
||||
private static (string type, string h1) GetTypeAndH1(AppSettings appSettings, string h1, List<string> lines, LineNumber lineNumber)
|
||||
@ -1275,14 +1207,22 @@ internal static partial class HelperMarkdown
|
||||
return (type, h1FromFile);
|
||||
}
|
||||
|
||||
private static int SetFrontMatterAndH1(AppSettings appSettings, ReadOnlyDictionary<string, MarkdownFileAndLines> relativeToCollection)
|
||||
private static int SetFrontMatterAndH1(AppSettings appSettings, Input input, ReadOnlyDictionary<string, MarkdownFileAndLines> relativeToCollection, ReadOnlyCollection<string> gitOthersModifiedAndDeletedExcludingStandardFiles)
|
||||
{
|
||||
int result = 0;
|
||||
List<string> results = [];
|
||||
bool gitCheck;
|
||||
string h1Line;
|
||||
string[] lines;
|
||||
string typeLine;
|
||||
TimeSpan timeSpan;
|
||||
string createdLine;
|
||||
string updatedLine;
|
||||
string lineDateTime;
|
||||
DateTime checkDateTime;
|
||||
DateTime creationDateTime;
|
||||
MarkdownFile markdownFile;
|
||||
string lineCreationFormat = "yyyy-MM-ddTHH:mm:ss.fffZ";
|
||||
foreach (KeyValuePair<string, MarkdownFileAndLines> relativeTo in relativeToCollection)
|
||||
{
|
||||
if (relativeTo.Value.Lines.Length == 0)
|
||||
@ -1293,6 +1233,10 @@ internal static partial class HelperMarkdown
|
||||
results.AddRange(lines);
|
||||
typeLine = $"type: \"{appSettings.DefaultNoteType}\"";
|
||||
h1Line = $"# {markdownFile.FileNameWithoutExtension}";
|
||||
creationDateTime = markdownFile.CreationDateTime > markdownFile.LastWriteDateTime ? markdownFile.LastWriteDateTime : markdownFile.CreationDateTime;
|
||||
gitCheck = gitOthersModifiedAndDeletedExcludingStandardFiles.Contains(markdownFile.File);
|
||||
createdLine = $"created: \"{creationDateTime.ToUniversalTime():yyyy-MM-ddTHH:mm:ss.fffZ}\"";
|
||||
updatedLine = $"updated: \"{markdownFile.LastWriteDateTime.ToUniversalTime():yyyy-MM-ddTHH:mm:ss.fffZ}\"";
|
||||
if (markdownFile.LineNumber.FrontMatterYamlEnd is null)
|
||||
{
|
||||
if (markdownFile.LineNumber.H1 is null)
|
||||
@ -1302,6 +1246,11 @@ internal static partial class HelperMarkdown
|
||||
results.Insert(0, string.Empty);
|
||||
}
|
||||
results.Insert(0, "---");
|
||||
if (gitCheck)
|
||||
{
|
||||
results.Insert(0, updatedLine);
|
||||
results.Insert(0, createdLine);
|
||||
}
|
||||
results.Insert(0, typeLine);
|
||||
results.Insert(0, "---");
|
||||
}
|
||||
@ -1315,9 +1264,42 @@ internal static partial class HelperMarkdown
|
||||
}
|
||||
if (markdownFile.LineNumber.Type is null)
|
||||
results.Insert(markdownFile.LineNumber.FrontMatterYamlEnd.Value, typeLine);
|
||||
if (markdownFile.LineNumber.H1 is not null && markdownFile.LineNumber.Type is not null)
|
||||
continue;
|
||||
if (gitCheck)
|
||||
{
|
||||
if (markdownFile.LineNumber.Updated is null)
|
||||
results.Insert(markdownFile.LineNumber.FrontMatterYamlEnd.Value, updatedLine);
|
||||
else
|
||||
{
|
||||
lineDateTime = results[markdownFile.LineNumber.Updated.Value].Split(": ")[1].Trim('"');
|
||||
if (!DateTime.TryParseExact(lineDateTime, lineCreationFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out checkDateTime))
|
||||
results[markdownFile.LineNumber.Updated.Value] = updatedLine;
|
||||
else
|
||||
{
|
||||
timeSpan = new(checkDateTime.Ticks - markdownFile.LastWriteDateTime.Ticks);
|
||||
if (timeSpan.TotalDays is > 1 or < -1)
|
||||
results[markdownFile.LineNumber.Updated.Value] = updatedLine;
|
||||
}
|
||||
}
|
||||
if (markdownFile.LineNumber.Created is null)
|
||||
results.Insert(markdownFile.LineNumber.FrontMatterYamlEnd.Value, createdLine);
|
||||
else
|
||||
{
|
||||
lineDateTime = results[markdownFile.LineNumber.Created.Value].Split(": ")[1].Trim('"');
|
||||
if (!DateTime.TryParseExact(lineDateTime, lineCreationFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out checkDateTime))
|
||||
results[markdownFile.LineNumber.Created.Value] = createdLine;
|
||||
else
|
||||
{
|
||||
timeSpan = new(checkDateTime.Ticks - creationDateTime.Ticks);
|
||||
if (timeSpan.TotalDays > 1)
|
||||
results[markdownFile.LineNumber.Created.Value] = createdLine;
|
||||
if (timeSpan.TotalDays < -1)
|
||||
File.SetCreationTime(markdownFile.File, checkDateTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (results.Count == lines.Length && string.Join('\r', lines) == string.Join('\r', results))
|
||||
continue;
|
||||
File.WriteAllLines(markdownFile.File, results);
|
||||
File.SetLastWriteTime(markdownFile.File, markdownFile.LastWriteDateTime);
|
||||
result += 1;
|
||||
@ -1331,13 +1313,14 @@ internal static partial class HelperMarkdown
|
||||
return new(result?.MarkdownFile, result?.Lines, result?.MarkdownFile.H1, result is null ? null : Path.GetRelativePath(markdownFile.Directory, Path.GetFullPath(result.MarkdownFile.File)));
|
||||
}
|
||||
|
||||
internal static void MarkdownWikiLinkVerification(AppSettings appSettings, ILogger<Worker> logger, List<string> args)
|
||||
internal static void MarkdownWikiLinkVerification(AppSettings appSettings, ILogger<Worker> logger, List<string> args, CancellationToken cancellationToken)
|
||||
{
|
||||
int updated;
|
||||
bool usePathCombine = false;
|
||||
Input input = GetInput(args);
|
||||
ReadOnlyDictionary<string, MarkdownFileAndLines> relativeToCollection;
|
||||
relativeToCollection = GetRelativeToCollection(appSettings, input);
|
||||
updated = SetFrontMatterAndH1(appSettings, relativeToCollection);
|
||||
ReadOnlyDictionary<string, MarkdownFileAndLines> relativeToCollection = GetRelativeToCollection(appSettings, input);
|
||||
ReadOnlyCollection<string> gitOthersModifiedAndDeletedExcludingStandardFiles = HelperGit.GetOthersModifiedAndDeletedExcludingStandardFiles(input.Source, usePathCombine, cancellationToken);
|
||||
updated = SetFrontMatterAndH1(appSettings, input, relativeToCollection, gitOthersModifiedAndDeletedExcludingStandardFiles);
|
||||
if (updated != 0)
|
||||
{
|
||||
relativeToCollection = GetRelativeToCollection(appSettings, input);
|
||||
@ -1383,18 +1366,4 @@ internal static partial class HelperMarkdown
|
||||
SaveColumnToCards(input, relativeToCollection);
|
||||
}
|
||||
|
||||
internal static void MarkdownConvertLinksForHugo(AppSettings appSettings, ILogger<Worker> logger, List<string> args)
|
||||
{
|
||||
Input input = GetInput(args);
|
||||
if (string.IsNullOrEmpty(input.Destination))
|
||||
throw new NotSupportedException("This method requires frontMatterYamlLines -d path!");
|
||||
List<Record> collection = GetWithLinksForHugo(appSettings, input);
|
||||
if (collection.Count == 0)
|
||||
logger.LogInformation("No files?");
|
||||
List<string> distinct = GetDistinct(collection);
|
||||
CreateMissingDirectories(distinct);
|
||||
foreach (Record record in collection)
|
||||
File.WriteAllLines(record.File, record.Lines);
|
||||
}
|
||||
|
||||
}
|
30
Helpers/HelperNPM.cs
Normal file
30
Helpers/HelperNPM.cs
Normal file
@ -0,0 +1,30 @@
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace File_Folder_Helper.Helpers;
|
||||
|
||||
internal static class HelperNPM
|
||||
{
|
||||
|
||||
internal static string RunCommand(string commandFileName, string commandToRun, string workingDirectory)
|
||||
{
|
||||
string result;
|
||||
if (!string.IsNullOrEmpty(commandFileName))
|
||||
File.WriteAllText(Path.Combine(workingDirectory, commandFileName), commandToRun);
|
||||
if (string.IsNullOrEmpty(workingDirectory))
|
||||
workingDirectory = Directory.GetDirectoryRoot(Directory.GetCurrentDirectory());
|
||||
ProcessStartInfo processStartInfo = new()
|
||||
{
|
||||
FileName = "cmd",
|
||||
RedirectStandardError = true,
|
||||
RedirectStandardInput = true,
|
||||
RedirectStandardOutput = true,
|
||||
WorkingDirectory = workingDirectory
|
||||
};
|
||||
Process? process = Process.Start(processStartInfo) ?? throw new Exception("Process should not be null.");
|
||||
process.StandardInput.WriteLine($"{commandToRun} & exit");
|
||||
process.WaitForExit();
|
||||
result = $"{process.StandardOutput.ReadToEnd()}{Environment.NewLine}{process.StandardError.ReadToEnd()}{Environment.NewLine}{process.ExitCode}";
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
@ -34,6 +34,7 @@ internal static class HelperSaveOrCopyContents
|
||||
log.LogInformation("{empty}", string.Empty);
|
||||
continue;
|
||||
}
|
||||
#pragma warning disable IDE0072
|
||||
string fileName = dfb switch
|
||||
{
|
||||
ConsoleKey.D => "Directories",
|
||||
@ -41,6 +42,7 @@ internal static class HelperSaveOrCopyContents
|
||||
ConsoleKey.B => "Both",
|
||||
_ => throw new NotSupportedException(),
|
||||
};
|
||||
#pragma warning restore IDE0072
|
||||
string filePathAndName = Path.Combine(parentDirectory, $"{fileName}.txt");
|
||||
if (dfb == ConsoleKey.F)
|
||||
collection = Directory.GetFiles(argsZero, "*", searchOption).ToList();
|
||||
@ -79,7 +81,7 @@ internal static class HelperSaveOrCopyContents
|
||||
foreach (string file in files)
|
||||
{
|
||||
fileName = Path.GetFileName(file);
|
||||
if (fileName == fileName.ToLower())
|
||||
if (fileName.Equals(fileName, StringComparison.CurrentCultureIgnoreCase))
|
||||
continue;
|
||||
File.Move(file, file.ToLower());
|
||||
filesRenamed++;
|
||||
|
100
Helpers/RijndaelEncryption.cs
Normal file
100
Helpers/RijndaelEncryption.cs
Normal file
@ -0,0 +1,100 @@
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace File_Folder_Helper.Helpers;
|
||||
|
||||
public static class RijndaelEncryption
|
||||
{ // cSpell:disable
|
||||
|
||||
/// <summary>
|
||||
/// Change the input key GUID when you use this code in your own program.
|
||||
/// Keep this input key very safe and prevent someone from decoding it some way!!
|
||||
/// Generated 2021-08-10
|
||||
/// </summary>
|
||||
internal const string _InputKey = "970CCEF6-4307-4F6A-9AC8-377DADB889BD";
|
||||
|
||||
/// <summary>
|
||||
/// Encrypt the given text and give the byte array back as a BASE64 string
|
||||
/// </summary>
|
||||
/// <param name="text">The text to encrypt</param>
|
||||
/// <param name="salt">The password salt</param>
|
||||
/// <returns>The encrypted text</returns>
|
||||
public static string Encrypt(string text, string salt)
|
||||
{
|
||||
string result;
|
||||
if (string.IsNullOrEmpty(text))
|
||||
throw new ArgumentNullException(nameof(text));
|
||||
#pragma warning disable SYSLIB0022
|
||||
RijndaelManaged aesAlg = NewRijndaelManaged(salt);
|
||||
#pragma warning restore
|
||||
ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
|
||||
MemoryStream msEncrypt = new();
|
||||
using (CryptoStream csEncrypt = new(msEncrypt, encryptor, CryptoStreamMode.Write))
|
||||
using (StreamWriter swEncrypt = new(csEncrypt))
|
||||
swEncrypt.Write(text);
|
||||
result = Convert.ToBase64String(msEncrypt.ToArray());
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if a string is base64 encoded
|
||||
/// </summary>
|
||||
/// <param name="base64String">The base64 encoded string</param>
|
||||
/// <returns></returns>
|
||||
public static bool IsBase64String(string base64String)
|
||||
{
|
||||
bool result;
|
||||
base64String = base64String.Trim();
|
||||
#pragma warning restore
|
||||
result = (base64String.Length % 4 == 0) && Regex.IsMatch(base64String, @"^[a-zA-Z0-9\+/]*={0,3}$", RegexOptions.None);
|
||||
#pragma warning restore
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decrypts the given text
|
||||
/// </summary>
|
||||
/// <param name="cipherText">The encrypted BASE64 text</param>
|
||||
/// <param name="salt">The password salt</param>
|
||||
/// <returns>De gedecrypte text</returns>
|
||||
public static string Decrypt(string cipherText, string salt)
|
||||
{
|
||||
if (string.IsNullOrEmpty(cipherText))
|
||||
throw new ArgumentNullException(nameof(cipherText));
|
||||
if (!IsBase64String(cipherText))
|
||||
throw new Exception("The cipherText input parameter is not base64 encoded");
|
||||
string text;
|
||||
#pragma warning disable SYSLIB0022
|
||||
RijndaelManaged aesAlg = NewRijndaelManaged(salt);
|
||||
#pragma warning restore
|
||||
ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
|
||||
byte[] cipher = Convert.FromBase64String(cipherText);
|
||||
using (MemoryStream msDecrypt = new(cipher))
|
||||
{
|
||||
using CryptoStream csDecrypt = new(msDecrypt, decryptor, CryptoStreamMode.Read);
|
||||
using StreamReader srDecrypt = new(csDecrypt);
|
||||
text = srDecrypt.ReadToEnd();
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new RijndaelManaged class and initialize it
|
||||
/// </summary>
|
||||
/// <param name="salt">The password salt</param>
|
||||
/// <returns></returns>
|
||||
#pragma warning disable SYSLIB0022, SYSLIB0041, CA5379
|
||||
private static RijndaelManaged NewRijndaelManaged(string salt)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(salt);
|
||||
byte[] saltBytes = Encoding.ASCII.GetBytes(salt);
|
||||
Rfc2898DeriveBytes key = new(_InputKey, saltBytes);
|
||||
RijndaelManaged aesAlg = new();
|
||||
#pragma warning restore
|
||||
aesAlg.Key = key.GetBytes(aesAlg.KeySize / 8);
|
||||
aesAlg.IV = key.GetBytes(aesAlg.BlockSize / 8);
|
||||
return aesAlg;
|
||||
}
|
||||
|
||||
}
|
@ -8,7 +8,6 @@ public record AppSettings(string Company,
|
||||
string[] ExcludeDirectoryNames,
|
||||
string[] ExcludeSchemes,
|
||||
string PersonBirthdayFormat,
|
||||
char[] PersonCharacters,
|
||||
char[] PersonTitleFilters,
|
||||
string WorkingDirectoryName)
|
||||
{
|
||||
|
@ -12,7 +12,6 @@ public class AppSettings
|
||||
public string[]? ExcludeDirectoryNames { get; set; }
|
||||
public string[]? ExcludeSchemes { get; set; }
|
||||
public string? PersonBirthdayFormat { get; set; }
|
||||
public string? PersonCharacters { get; set; }
|
||||
public string? PersonTitleFilters { get; set; }
|
||||
public string? WorkingDirectoryName { get; set; }
|
||||
|
||||
@ -22,6 +21,23 @@ public class AppSettings
|
||||
return result;
|
||||
}
|
||||
|
||||
private static void PreVerify(IConfigurationRoot configurationRoot, AppSettings? appSettings)
|
||||
{
|
||||
if (appSettings?.Company is null)
|
||||
{
|
||||
List<string> paths = [];
|
||||
foreach (IConfigurationProvider configurationProvider in configurationRoot.Providers)
|
||||
{
|
||||
if (configurationProvider is not Microsoft.Extensions.Configuration.Json.JsonConfigurationProvider jsonConfigurationProvider)
|
||||
continue;
|
||||
if (jsonConfigurationProvider.Source.FileProvider is not Microsoft.Extensions.FileProviders.PhysicalFileProvider physicalFileProvider)
|
||||
continue;
|
||||
paths.Add(physicalFileProvider.Root);
|
||||
}
|
||||
throw new NotSupportedException($"Not found!{Environment.NewLine}{string.Join(Environment.NewLine, paths.Distinct())}");
|
||||
}
|
||||
}
|
||||
|
||||
private static Models.AppSettings Get(AppSettings? appSettings)
|
||||
{
|
||||
Models.AppSettings result;
|
||||
@ -30,7 +46,6 @@ public class AppSettings
|
||||
if (appSettings?.ExcludeDirectoryNames is null) throw new NullReferenceException(nameof(appSettings.ExcludeDirectoryNames));
|
||||
if (appSettings?.ExcludeSchemes is null) throw new NullReferenceException(nameof(appSettings.ExcludeSchemes));
|
||||
if (appSettings?.PersonBirthdayFormat is null) throw new NullReferenceException(nameof(appSettings.PersonBirthdayFormat));
|
||||
if (appSettings?.PersonCharacters is null) throw new NullReferenceException(nameof(appSettings.PersonCharacters));
|
||||
if (appSettings?.PersonTitleFilters is null) throw new NullReferenceException(nameof(appSettings.PersonTitleFilters));
|
||||
if (appSettings?.WorkingDirectoryName is null) throw new NullReferenceException(nameof(appSettings.WorkingDirectoryName));
|
||||
result = new(
|
||||
@ -39,7 +54,6 @@ public class AppSettings
|
||||
appSettings.ExcludeDirectoryNames,
|
||||
appSettings.ExcludeSchemes,
|
||||
appSettings.PersonBirthdayFormat,
|
||||
appSettings.PersonCharacters.ToArray(),
|
||||
appSettings.PersonTitleFilters.ToArray(),
|
||||
appSettings.WorkingDirectoryName
|
||||
);
|
||||
@ -52,20 +66,7 @@ public class AppSettings
|
||||
#pragma warning disable IL3050, IL2026
|
||||
AppSettings? appSettings = configurationRoot.Get<AppSettings>();
|
||||
#pragma warning restore IL3050, IL2026
|
||||
if (appSettings?.Company is null)
|
||||
{
|
||||
foreach (IConfigurationProvider configurationProvider in configurationRoot.Providers)
|
||||
{
|
||||
if (configurationProvider is not Microsoft.Extensions.Configuration.Json.JsonConfigurationProvider jsonConfigurationProvider)
|
||||
continue;
|
||||
if (jsonConfigurationProvider.Source.FileProvider is not Microsoft.Extensions.FileProviders.PhysicalFileProvider physicalFileProvider)
|
||||
continue;
|
||||
if (!physicalFileProvider.Root.Contains("UserSecrets"))
|
||||
continue;
|
||||
throw new NotSupportedException(physicalFileProvider.Root);
|
||||
}
|
||||
throw new NotSupportedException("Not found!");
|
||||
}
|
||||
PreVerify(configurationRoot, appSettings);
|
||||
result = Get(appSettings);
|
||||
return result;
|
||||
}
|
||||
|
57
Worker.cs
57
Worker.cs
@ -1,6 +1,7 @@
|
||||
using File_Folder_Helper.Models;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using WindowsShortcutFactory;
|
||||
|
||||
namespace File_Folder_Helper;
|
||||
|
||||
@ -61,10 +62,35 @@ public class Worker : BackgroundService
|
||||
public override Task StopAsync(CancellationToken cancellationToken) =>
|
||||
base.StopAsync(cancellationToken);
|
||||
|
||||
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
||||
private void CreateWindowsShortcut()
|
||||
{
|
||||
if (!stoppingToken.IsCancellationRequested)
|
||||
await Task.Delay(500, stoppingToken);
|
||||
object? assemblyName = AppContext.GetData("AssemblyName");
|
||||
string sendToDirectory = Environment.GetFolderPath(Environment.SpecialFolder.SendTo);
|
||||
string localApplicationData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
|
||||
if (Directory.Exists(sendToDirectory) && Directory.Exists(localApplicationData) && assemblyName is string assemblyNameValue)
|
||||
{
|
||||
string shortcut = Path.Combine(sendToDirectory, $"{assemblyNameValue}.lnk");
|
||||
string directory = Path.Combine(localApplicationData, _AppSettings.WorkingDirectoryName, assemblyNameValue);
|
||||
if (!Directory.Exists(directory))
|
||||
_ = Directory.CreateDirectory(directory);
|
||||
if (!File.Exists(sendToDirectory))
|
||||
{
|
||||
WindowsShortcut windowsShortcut = new()
|
||||
{
|
||||
Arguments = "s X C:/ProgramData Day-Helper-2024-01-07 1",
|
||||
Path = Path.Combine(directory, $"{assemblyNameValue}.exe"),
|
||||
WorkingDirectory = AppContext.BaseDirectory
|
||||
};
|
||||
windowsShortcut.Save(shortcut);
|
||||
windowsShortcut.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override async Task ExecuteAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
if (!cancellationToken.IsCancellationRequested)
|
||||
await Task.Delay(500, cancellationToken);
|
||||
if (_AppSettings is null)
|
||||
throw new NullReferenceException(nameof(_AppSettings));
|
||||
try
|
||||
@ -84,7 +110,10 @@ public class Worker : BackgroundService
|
||||
if (singleCharIndex is not null)
|
||||
_Args.RemoveAt(singleCharIndex.Value);
|
||||
if (_Args.Count == 0)
|
||||
_Logger.LogInformation("Must pass a argument!");
|
||||
{
|
||||
_Logger.LogWarning("Must pass a argument!");
|
||||
CreateWindowsShortcut();
|
||||
}
|
||||
else if (Directory.Exists(_Args[0]) && File.Exists(Path.Combine(_Args[0], string.Concat(Path.GetFileName(_Args[0]), ".dll"))))
|
||||
Helpers.HelperILMerge.ILMerge(_Args[0]);
|
||||
else if (Directory.Exists(_Args[0]))
|
||||
@ -100,20 +129,20 @@ public class Worker : BackgroundService
|
||||
_Logger.LogInformation("E) Everything delete recursive,");
|
||||
_Logger.LogInformation("F) Find and delete all *.log.* files then empty directories,");
|
||||
_Logger.LogInformation("G) Genealogical Data Communication,");
|
||||
_Logger.LogInformation("H) Hardcoded file search and sort,");
|
||||
// H
|
||||
_Logger.LogInformation("I) Ignore case and rename files to lowercase,");
|
||||
_Logger.LogInformation("J) Set Date from Json Entry,");
|
||||
_Logger.LogInformation("K) Kanban support,");
|
||||
_Logger.LogInformation("L) Log Merge (APC Log [0-9(8)]_*.log),");
|
||||
_Logger.LogInformation("N) Create Note Files,");
|
||||
_Logger.LogInformation("M) Markdown Wiki Link Verification,");
|
||||
_Logger.LogInformation("N) Create Note Files,");
|
||||
_Logger.LogInformation("O) Oracle tnsNames.ora,");
|
||||
_Logger.LogInformation("P) PDF parse,");
|
||||
// Q
|
||||
_Logger.LogInformation("R) Rename to old, copy, delete old,");
|
||||
_Logger.LogInformation("S) Set Date from Zip Entry,");
|
||||
_Logger.LogInformation("T) *Ticks ~~Too long rename~~,");
|
||||
_Logger.LogInformation("U) Links for Hugo,");
|
||||
// U
|
||||
// V
|
||||
// W
|
||||
_Logger.LogInformation("X) Day Helpers,");
|
||||
@ -140,9 +169,6 @@ public class Worker : BackgroundService
|
||||
case ConsoleKey.G:
|
||||
Helpers.HelperGenealogicalDataCommunication.FileSystemToGenealogicalDataCommunication(_AppSettings, _Logger, _Args);
|
||||
break;
|
||||
case ConsoleKey.H:
|
||||
Helpers.HelperHardcodedFileSearchAndSort.HardcodedFileSearchAndSort(_Logger, _Args[0]);
|
||||
break;
|
||||
case ConsoleKey.I:
|
||||
Helpers.HelperSaveOrCopyContents.IgnoreCaseAndRenameFilesToLowercase(_Logger, _Args[0]);
|
||||
break;
|
||||
@ -150,7 +176,7 @@ public class Worker : BackgroundService
|
||||
Helpers.HelperPackageFilesByDate.SetDateFromJsonEntry(_Logger, _Args[0]);
|
||||
break;
|
||||
case ConsoleKey.K:
|
||||
Helpers.HelperKanbanMetadata.SetMetadata(_Logger, _AppSettings, _Args[0], addTicks: true);
|
||||
Helpers.HelperKanbanMetadata.SetMetadata(_Logger, _AppSettings, _Args[0]);
|
||||
break;
|
||||
case ConsoleKey.L:
|
||||
Helpers.HelperLogMerge.LogMerge(_Args[0]);
|
||||
@ -160,8 +186,8 @@ public class Worker : BackgroundService
|
||||
break;
|
||||
case ConsoleKey.M:
|
||||
if (_Args[0].EndsWith(".kanbn") && Directory.Exists(_Args[0]))
|
||||
Helpers.HelperKanbanMetadata.SetMetadata(_Logger, _AppSettings, _Args[0], addTicks: false);
|
||||
Helpers.HelperMarkdown.MarkdownWikiLinkVerification(_AppSettings, _Logger, _Args);
|
||||
Helpers.HelperKanbanMetadata.SetMetadata(_Logger, _AppSettings, _Args[0]);
|
||||
Helpers.HelperMarkdown.MarkdownWikiLinkVerification(_AppSettings, _Logger, _Args, cancellationToken);
|
||||
break;
|
||||
case ConsoleKey.O:
|
||||
Helpers.HelperFindReplace.UpdateTnsNames(_Logger, _Args);
|
||||
@ -181,11 +207,8 @@ public class Worker : BackgroundService
|
||||
// Helpers.HelperTooLong.TooLong(_Args[0], delete: false);
|
||||
// Helpers.HelperTooLong.TooLong(_Args[0], delete: true);
|
||||
break;
|
||||
case ConsoleKey.U:
|
||||
Helpers.HelperMarkdown.MarkdownConvertLinksForHugo(_AppSettings, _Logger, _Args);
|
||||
break;
|
||||
case ConsoleKey.X:
|
||||
Helpers.HelperDay.Select(_AppSettings, _Logger, _Args);
|
||||
Helpers.HelperDay.Select(_AppSettings, _Logger, _Args, cancellationToken);
|
||||
break;
|
||||
case ConsoleKey.Y:
|
||||
Helpers.HelperZipFilesBy.ZipFilesByDirectoryWithFile(_Logger, _Args[0]);
|
||||
|
@ -1,10 +1,11 @@
|
||||
{
|
||||
"scripts": {
|
||||
"prettier.check": "prettier . --check",
|
||||
"prettier.write": "prettier . --write",
|
||||
"kanbn.board": "kanbn board",
|
||||
"garbage-collect": "git gc",
|
||||
"git:pre-commit": "cp .vscode/pre-commit .git/hooks/ && chmod +x .git/hooks/pre-commit && echo 'hook copied'",
|
||||
"kanbn.board.json": "kanbn board -j > .kanbn/board.json",
|
||||
"garbage-collect": "git gc"
|
||||
"kanbn.board": "kanbn board",
|
||||
"prettier.check": "prettier . --check",
|
||||
"prettier.write": "prettier . --write"
|
||||
},
|
||||
"devDependencies": {
|
||||
"prettier": "3.0.0"
|
||||
|
Loading…
x
Reference in New Issue
Block a user