From c1a4eb4808edd1709fda374d506adb49bcc2ee29 Mon Sep 17 00:00:00 2001 From: Mike Phares Date: Fri, 22 Sep 2023 18:16:55 -0700 Subject: [PATCH] Init --- .editorconfig | 243 +++++++++++++++++++++++ .gitignore | 329 +++++++++++++++++++++++++++++++ .prettierignore | 3 + .vscode/format-report.json | 1 + .vscode/launch.json | 41 ++++ .vscode/settings.json | 37 ++++ .vscode/tasks.json | 107 ++++++++++ File-Watcher.csproj | 18 ++ Helpers/HelperCreateNoteFiles.cs | 287 +++++++++++++++++++++++++++ Models/AppSettings.cs | 26 +++ Models/Binder/.editorconfig | 2 + Models/Binder/AppSettings.cs | 57 ++++++ Program.cs | 58 ++++++ README.md | 20 ++ Worker.cs | 78 ++++++++ package-lock.json | 35 ++++ package.json | 10 + 17 files changed, 1352 insertions(+) create mode 100644 .editorconfig create mode 100644 .gitignore create mode 100644 .prettierignore create mode 100644 .vscode/format-report.json create mode 100644 .vscode/launch.json create mode 100644 .vscode/settings.json create mode 100644 .vscode/tasks.json create mode 100644 File-Watcher.csproj create mode 100644 Helpers/HelperCreateNoteFiles.cs create mode 100644 Models/AppSettings.cs create mode 100644 Models/Binder/.editorconfig create mode 100644 Models/Binder/AppSettings.cs create mode 100644 Program.cs create mode 100644 README.md create mode 100644 Worker.cs create mode 100644 package-lock.json create mode 100644 package.json diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..046ef9f --- /dev/null +++ b/.editorconfig @@ -0,0 +1,243 @@ +[*.cs] +csharp_indent_block_contents = true +csharp_indent_braces = false +csharp_indent_case_contents = true +csharp_indent_case_contents_when_block = true +csharp_indent_labels = one_less_than_current +csharp_indent_switch_labels = true +csharp_new_line_before_catch = true +csharp_new_line_before_else = true +csharp_new_line_before_finally = true +csharp_new_line_before_members_in_anonymous_types = true +csharp_new_line_before_members_in_object_initializers = true +csharp_new_line_before_open_brace = all +csharp_new_line_between_query_expression_clauses = true +csharp_prefer_braces = false +csharp_prefer_simple_default_expression = true:warning +csharp_prefer_simple_using_statement = true:warning +csharp_prefer_static_local_function = true:warning +csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async +csharp_preserve_single_line_blocks = true +csharp_preserve_single_line_statements = false +csharp_space_after_cast = false +csharp_space_after_colon_in_inheritance_clause = true +csharp_space_after_comma = true +csharp_space_after_dot = false +csharp_space_after_keywords_in_control_flow_statements = true +csharp_space_after_semicolon_in_for_statement = true +csharp_space_around_binary_operators = before_and_after +csharp_space_around_declaration_statements = false +csharp_space_before_colon_in_inheritance_clause = true +csharp_space_before_comma = false +csharp_space_before_dot = false +csharp_space_before_open_square_brackets = false +csharp_space_before_semicolon_in_for_statement = false +csharp_space_between_empty_square_brackets = false +csharp_space_between_method_call_empty_parameter_list_parentheses = false +csharp_space_between_method_call_name_and_opening_parenthesis = false +csharp_space_between_method_call_parameter_list_parentheses = false +csharp_space_between_method_declaration_empty_parameter_list_parentheses = false +csharp_space_between_method_declaration_name_and_open_parenthesis = false +csharp_space_between_method_declaration_parameter_list_parentheses = false +csharp_space_between_parentheses = false +csharp_space_between_square_brackets = false +csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = true +csharp_style_allow_blank_lines_between_consecutive_braces_experimental = true +csharp_style_allow_embedded_statements_on_same_line_experimental = true +csharp_style_conditional_delegate_call = true +csharp_style_deconstructed_variable_declaration = false +csharp_style_expression_bodied_accessors = when_on_single_line:warning +csharp_style_expression_bodied_constructors = when_on_single_line:warning +csharp_style_expression_bodied_indexers = when_on_single_line:warning +csharp_style_expression_bodied_lambdas = when_on_single_line:warning +csharp_style_expression_bodied_local_functions = when_on_single_line:warning +csharp_style_expression_bodied_methods = when_on_single_line:warning +csharp_style_expression_bodied_operators = when_on_single_line:warning +csharp_style_expression_bodied_properties = when_on_single_line:warning +csharp_style_implicit_object_creation_when_type_is_apparent = true:warning +csharp_style_inlined_variable_declaration = false +csharp_style_namespace_declarations = file_scoped:warning +csharp_style_pattern_local_over_anonymous_function = true:warning +csharp_style_pattern_matching_over_as_with_null_check = true:warning +csharp_style_pattern_matching_over_is_with_cast_check = true:warning +csharp_style_prefer_index_operator = true:warning +csharp_style_prefer_not_pattern = true:warning +csharp_style_prefer_null_check_over_type_check = true +csharp_style_prefer_pattern_matching = true:warning +csharp_style_prefer_range_operator = true:warning +csharp_style_prefer_switch_expression = true:warning +csharp_style_throw_expression = true +csharp_style_unused_value_assignment_preference = discard_variable:warning +csharp_style_unused_value_expression_statement_preference = discard_variable:warning +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_code_quality_unused_parameters = all +dotnet_code_quality_unused_parameters = non_public # IDE0060: Remove unused parameter +dotnet_code_quality.CAXXXX.api_surface = private, internal +dotnet_diagnostic.CA1825.severity = warning # CA1823: 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.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.IDE0005.severity = warning # Using directive is unnecessary +dotnet_diagnostic.IDE0047.severity = warning # IDE0047: Parentheses can be removed +dotnet_diagnostic.IDE0060.severity = warning # IDE0060: Remove unused parameter +dotnet_naming_rule.abstract_method_should_be_pascal_case.severity = warning +dotnet_naming_rule.abstract_method_should_be_pascal_case.style = pascal_case +dotnet_naming_rule.abstract_method_should_be_pascal_case.symbols = abstract_method +dotnet_naming_rule.class_should_be_pascal_case.severity = warning +dotnet_naming_rule.class_should_be_pascal_case.style = pascal_case +dotnet_naming_rule.class_should_be_pascal_case.symbols = class +dotnet_naming_rule.delegate_should_be_pascal_case.severity = warning +dotnet_naming_rule.delegate_should_be_pascal_case.style = pascal_case +dotnet_naming_rule.delegate_should_be_pascal_case.symbols = delegate +dotnet_naming_rule.enum_should_be_pascal_case.severity = warning +dotnet_naming_rule.enum_should_be_pascal_case.style = pascal_case +dotnet_naming_rule.enum_should_be_pascal_case.symbols = enum +dotnet_naming_rule.event_should_be_pascal_case.severity = warning +dotnet_naming_rule.event_should_be_pascal_case.style = pascal_case +dotnet_naming_rule.event_should_be_pascal_case.symbols = event +dotnet_naming_rule.interface_should_be_begins_with_i.severity = warning +dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i +dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface +dotnet_naming_rule.method_should_be_pascal_case.severity = warning +dotnet_naming_rule.method_should_be_pascal_case.style = pascal_case +dotnet_naming_rule.method_should_be_pascal_case.symbols = method +dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = warning +dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case +dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members +dotnet_naming_rule.private_method_should_be_pascal_case.severity = warning +dotnet_naming_rule.private_method_should_be_pascal_case.style = pascal_case +dotnet_naming_rule.private_method_should_be_pascal_case.symbols = private_method +dotnet_naming_rule.private_or_internal_field_should_be_private_of_internal_field.severity = warning +dotnet_naming_rule.private_or_internal_field_should_be_private_of_internal_field.style = private_of_internal_field +dotnet_naming_rule.private_or_internal_field_should_be_private_of_internal_field.symbols = private_or_internal_field +dotnet_naming_rule.private_or_internal_static_field_should_be_private_of_internal_field.severity = warning +dotnet_naming_rule.private_or_internal_static_field_should_be_private_of_internal_field.style = private_of_internal_field +dotnet_naming_rule.private_or_internal_static_field_should_be_private_of_internal_field.symbols = private_or_internal_static_field +dotnet_naming_rule.property_should_be_pascal_case.severity = warning +dotnet_naming_rule.property_should_be_pascal_case.style = pascal_case +dotnet_naming_rule.property_should_be_pascal_case.symbols = property +dotnet_naming_rule.public_or_protected_field_should_be_private_of_internal_field.severity = warning +dotnet_naming_rule.public_or_protected_field_should_be_private_of_internal_field.style = private_of_internal_field +dotnet_naming_rule.public_or_protected_field_should_be_private_of_internal_field.symbols = public_or_protected_field +dotnet_naming_rule.static_field_should_be_pascal_case.severity = warning +dotnet_naming_rule.static_field_should_be_pascal_case.style = pascal_case +dotnet_naming_rule.static_field_should_be_pascal_case.symbols = static_field +dotnet_naming_rule.static_method_should_be_pascal_case.severity = warning +dotnet_naming_rule.static_method_should_be_pascal_case.style = pascal_case +dotnet_naming_rule.static_method_should_be_pascal_case.symbols = static_method +dotnet_naming_rule.struct_should_be_pascal_case.severity = warning +dotnet_naming_rule.struct_should_be_pascal_case.style = pascal_case +dotnet_naming_rule.struct_should_be_pascal_case.symbols = struct +dotnet_naming_rule.types_should_be_pascal_case.severity = warning +dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case +dotnet_naming_rule.types_should_be_pascal_case.symbols = types +dotnet_naming_style.begins_with_i.capitalization = pascal_case +dotnet_naming_style.begins_with_i.required_prefix = I +dotnet_naming_style.begins_with_i.required_suffix = +dotnet_naming_style.begins_with_i.word_separator = +dotnet_naming_style.pascal_case.capitalization = pascal_case +dotnet_naming_style.pascal_case.required_prefix = +dotnet_naming_style.pascal_case.required_suffix = +dotnet_naming_style.pascal_case.word_separator = +dotnet_naming_style.private_of_internal_field.capitalization = pascal_case +dotnet_naming_style.private_of_internal_field.required_prefix = _ +dotnet_naming_style.private_of_internal_field.required_suffix = +dotnet_naming_style.private_of_internal_field.word_separator = +dotnet_naming_symbols.abstract_method.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.abstract_method.applicable_kinds = method +dotnet_naming_symbols.abstract_method.required_modifiers = abstract +dotnet_naming_symbols.class.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.class.applicable_kinds = class +dotnet_naming_symbols.class.required_modifiers = +dotnet_naming_symbols.delegate.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.delegate.applicable_kinds = delegate +dotnet_naming_symbols.delegate.required_modifiers = +dotnet_naming_symbols.enum.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.enum.applicable_kinds = enum +dotnet_naming_symbols.enum.required_modifiers = +dotnet_naming_symbols.event.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.event.applicable_kinds = event +dotnet_naming_symbols.event.required_modifiers = +dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.interface.applicable_kinds = interface +dotnet_naming_symbols.interface.required_modifiers = +dotnet_naming_symbols.method.applicable_accessibilities = public +dotnet_naming_symbols.method.applicable_kinds = method +dotnet_naming_symbols.method.required_modifiers = +dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method +dotnet_naming_symbols.non_field_members.required_modifiers = +dotnet_naming_symbols.private_method.applicable_accessibilities = private +dotnet_naming_symbols.private_method.applicable_kinds = method +dotnet_naming_symbols.private_method.required_modifiers = +dotnet_naming_symbols.private_or_internal_field.applicable_accessibilities = internal, private, private_protected +dotnet_naming_symbols.private_or_internal_field.applicable_kinds = field +dotnet_naming_symbols.private_or_internal_field.required_modifiers = +dotnet_naming_symbols.private_or_internal_static_field.applicable_accessibilities = internal, private, private_protected +dotnet_naming_symbols.private_or_internal_static_field.applicable_kinds = field +dotnet_naming_symbols.private_or_internal_static_field.required_modifiers = static +dotnet_naming_symbols.property.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.property.applicable_kinds = property +dotnet_naming_symbols.property.required_modifiers = +dotnet_naming_symbols.public_or_protected_field.applicable_accessibilities = public, protected +dotnet_naming_symbols.public_or_protected_field.applicable_kinds = field +dotnet_naming_symbols.public_or_protected_field.required_modifiers = +dotnet_naming_symbols.static_field.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.static_field.applicable_kinds = field +dotnet_naming_symbols.static_field.required_modifiers = static +dotnet_naming_symbols.static_method.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.static_method.applicable_kinds = method +dotnet_naming_symbols.static_method.required_modifiers = static +dotnet_naming_symbols.struct.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.struct.applicable_kinds = struct +dotnet_naming_symbols.struct.required_modifiers = +dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum +dotnet_naming_symbols.types.required_modifiers = +dotnet_remove_unnecessary_suppression_exclusions = 0 +dotnet_separate_import_directive_groups = false +dotnet_sort_system_directives_first = false +dotnet_style_allow_multiple_blank_lines_experimental = false:warning +dotnet_style_allow_statement_immediately_after_block_experimental = true +dotnet_style_coalesce_expression = true +dotnet_style_collection_initializer = true:warning +dotnet_style_explicit_tuple_names = true:warning +dotnet_style_namespace_match_folder = true +dotnet_style_null_propagation = true:warning +dotnet_style_object_initializer = true:warning +dotnet_style_operator_placement_when_wrapping = beginning_of_line +dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity +dotnet_style_parentheses_in_other_binary_operators = always_for_clarity +dotnet_style_parentheses_in_other_operators = never_if_unnecessary +dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity +dotnet_style_predefined_type_for_locals_parameters_members = true +dotnet_style_predefined_type_for_member_access = true +dotnet_style_prefer_auto_properties = true:warning +dotnet_style_prefer_compound_assignment = true:warning +dotnet_style_prefer_conditional_expression_over_assignment = false +dotnet_style_prefer_conditional_expression_over_return = false +dotnet_style_prefer_inferred_anonymous_type_member_names = true:warning +dotnet_style_prefer_inferred_tuple_names = true:warning +dotnet_style_prefer_is_null_check_over_reference_equality_method = true:warning +dotnet_style_prefer_simplified_boolean_expressions = true:warning +dotnet_style_prefer_simplified_interpolation = true +dotnet_style_qualification_for_event = false:error +dotnet_style_qualification_for_field = false +dotnet_style_qualification_for_method = false:error +dotnet_style_qualification_for_property = false:error +dotnet_style_readonly_field = true:warning +dotnet_style_require_accessibility_modifiers = for_non_interface_members +end_of_line = crlf +file_header_template = unset +indent_size = 4 +indent_style = space +insert_final_newline = false +root = true +tab_width = 4 +# https://docs.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1822 +# https://github.com/dotnet/aspnetcore/blob/main/.editorconfig +# https://github.com/dotnet/project-system/blob/main/.editorconfig \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0c04d1d --- /dev/null +++ b/.gitignore @@ -0,0 +1,329 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +bld/ +[Bb]in/ +[Oo]bj/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ +**/Properties/launchSettings.json + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# JetBrains Rider +.idea/ +*.sln.iml + +# CodeRush +.cr/ + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ \ No newline at end of file diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..cbd1d3f --- /dev/null +++ b/.prettierignore @@ -0,0 +1,3 @@ +/* + +!/.kanbn diff --git a/.vscode/format-report.json b/.vscode/format-report.json new file mode 100644 index 0000000..0637a08 --- /dev/null +++ b/.vscode/format-report.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..db9b413 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,41 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": ".NET Core Launch (console)", + "type": "coreclr", + "request": "launch", + "preLaunchTask": "build", + "program": "${workspaceFolder}/bin/Debug/net7.0/win-x64/File-Folder-Helper.dll", + "args": [ + "s", + "\\\\messv02ecc1.ec.local\\EC_EDA\\Staging\\Traces\\HTR-PLC\\R72-PLC\\PollPath" + ], + "cwd": "${workspaceFolder}", + "console": "integratedTerminal", + "stopAtEntry": false + }, + { + "name": ".NET Core Attach", + "type": "coreclr", + "request": "attach" + } + ] +} +// dotnet build +// dotnet run "s" "\\messv02ecc1.ec.local\EC_EDA\Staging\Traces\HTR-PLC\R45-PLC\PollPath" +// dotnet run "s" "\\messv02ecc1.ec.local\EC_EDA\Staging\Traces\HTR-PLC\R47-PLC\PollPath" +// dotnet run "s" "\\messv02ecc1.ec.local\EC_EDA\Staging\Traces\HTR-PLC\R49-PLC\PollPath" +// dotnet run "s" "\\messv02ecc1.ec.local\EC_EDA\Staging\Traces\HTR-PLC\R51-PLC\PollPath" +// dotnet run "s" "\\messv02ecc1.ec.local\EC_EDA\Staging\Traces\HTR-PLC\R70-PLC\PollPath" +// dotnet run "s" "\\messv02ecc1.ec.local\EC_EDA\Staging\Traces\HTR-PLC\R72-PLC\PollPath" +// dotnet run "s" "\\messv02ecc1.ec.local\EC_EDA\Staging\Traces\HTR-PLC\R73-PLC\PollPath" +// dotnet run "s" "\\messv02ecc1.ec.local\EC_EDA\Staging\Traces\HTR-PLC\R74-PLC\PollPath" +// dotnet run "s" "C:/Users/phares/.nuget/packages" +// dotnet run "s" "D:/ProgramData/EC_EAFRepository/nupkg" +// dotnet run "s" "D:/Baget/packages" +// dotnet run "s" "\\messdv002.na.infineon.com\Candela\BaGet\packages" +// dotnet run "s" "T:/MESAFIBACKLOG/06_SourceCode/MESAFIBACKLOG/Adaptation/.kanbn" \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..ed99375 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,37 @@ +{ + "[markdown]": { + "editor.wordWrap": "off" + }, + "files.exclude": { + "**/.git": false, + "**/node_modules": true + }, + "files.watcherExclude": { + "**/node_modules": true + }, + "cSpell.words": [ + "ASPNETCORE", + "BIRT", + "CHIL", + "DEAT", + "endianness", + "FAMC", + "FAMS", + "GIVN", + "HUSB", + "INDI", + "Infineon", + "Kanban", + "kanbn", + "Kofax", + "NSFX", + "OBJE", + "onenote", + "pged", + "Phares", + "Serilog", + "SUBM", + "SURN", + "SYSLIB" + ] +} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..45cab2e --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,107 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "User Secrets Init", + "command": "dotnet", + "type": "process", + "args": [ + "user-secrets", + "-p", + "${workspaceFolder}/File-Watcher.csproj", + "init" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "User Secrets Set", + "command": "dotnet", + "type": "process", + "args": [ + "user-secrets", + "-p", + "${workspaceFolder}/File-Watcher.csproj", + "set", + "asdf", + "6516d19d6569" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "Format", + "command": "dotnet", + "type": "process", + "args": [ + "format", + "--report", + ".vscode", + "--verbosity", + "detailed", + "--severity", + "warn" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "build", + "command": "dotnet", + "type": "process", + "args": [ + "build", + "${workspaceFolder}/File-Watcher.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "publish", + "command": "dotnet", + "type": "process", + "args": [ + "publish", + "${workspaceFolder}/File-Watcher.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "watch", + "command": "dotnet", + "type": "process", + "args": [ + "watch", + "run", + "--project", + "${workspaceFolder}/File-Watcher.csproj" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "Publish AOT", + "command": "dotnet", + "type": "process", + "args": [ + "publish", + "-r", + "win-x64", + "-c", + "Release", + "-p:PublishAot=true", + "--source", + "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet7/nuget/v3/index.json", + "${workspaceFolder}/File-Watcher.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "File-Watcher AOT s V Helpers", + "type": "shell", + "command": "& L:/DevOps/Mesa_FI/File-Watcher/bin/Release/net7.0/win-x64/publish/File-Watcher.exe s V Helpers", + "problemMatcher": [] + } + ] +} \ No newline at end of file diff --git a/File-Watcher.csproj b/File-Watcher.csproj new file mode 100644 index 0000000..a4ca5e6 --- /dev/null +++ b/File-Watcher.csproj @@ -0,0 +1,18 @@ + + + enable + enable + Exe + net7.0 + b6f34b8e-5026-41d4-9c28-6516d19d6569 + + + + + + + + + + + \ No newline at end of file diff --git a/Helpers/HelperCreateNoteFiles.cs b/Helpers/HelperCreateNoteFiles.cs new file mode 100644 index 0000000..5ffd2c0 --- /dev/null +++ b/Helpers/HelperCreateNoteFiles.cs @@ -0,0 +1,287 @@ +using System.Globalization; +using System.Text; +using System.Text.RegularExpressions; + +namespace File_Watcher.Helpers; + +internal static partial class HelperCreateNoteFiles +{ + + [GeneratedRegex("[^a-z0-9-]")] + private static partial Regex AlphaNumOnly(); + + private static string? GetTags(string tagsText) + { + string? result; + StringBuilder stringBuilder = new(); + if (string.IsNullOrEmpty(tagsText)) + result = null; + else + { + string[] segments; + _ = stringBuilder.AppendLine("tags:"); + string[] tags = tagsText.Split(';', StringSplitOptions.RemoveEmptyEntries); + foreach (string tag in tags) + { + segments = tag.Split(':'); + _ = stringBuilder.AppendLine($"- '{segments.First()}'"); + } + result = stringBuilder.ToString().Trim(); + } + return result; + } + + private static string? GetLinks(string type, string linksText) + { + string? result; + StringBuilder stringBuilder = new(); + if (!string.IsNullOrEmpty(linksText)) + result = null; + else + { + string linkLower; + string[] segments; + string[] links = linksText.Split(';', StringSplitOptions.RemoveEmptyEntries); + foreach (string link in links) + { + segments = link.Split(':'); + linkLower = AlphaNumOnly().Replace(segments.First().Trim().ToLower(), "-").Replace("--", "-"); + if (segments.Length == 1) + _ = stringBuilder.AppendLine($"- [[{type}/{linkLower}]]"); + else if (segments.Length == 2) + _ = stringBuilder.AppendLine($"- [{type}/{linkLower}]({segments.Last()})"); + else + continue; + } + result = stringBuilder.ToString().Trim(); + } + return result; + } + + private static string? GetAttributes(string[] columns, string[]? headerColumns, int expectedCount) + { + string? result; + if (headerColumns is null || columns.Length <= expectedCount) + result = null; + else + { + StringBuilder stringBuilder = new(); + for (int j = expectedCount; j < columns.Length; j++) + { + if (headerColumns.Length <= j) + continue; + _ = stringBuilder.AppendLine($"{headerColumns[j].Trim()}: '{columns[j].Trim()}'"); + } + result = stringBuilder.ToString().Trim(); + } + return result; + } + + private static void CleanExistingFiles(string directory, long ticks) + { + string check; + string[] lines; + string checkFile; + string? fileDirectory; + string checkDirectory; + bool circularReference; + string fileNameWithoutExtension; + char altDrive = directory[0] is 'c' or 'C' ? 'D' : 'C'; + string[] files = Directory.GetFiles(directory, "*.md", SearchOption.AllDirectories); + string match = ",*** *** *** *** *** *** *** *** ***,*** *** *** *** *** *** *** *** ***,*** *** *** *** *** *** *** *** ***,,TODO:,*** *** *** *** *** *** *** *** ***,*** *** *** *** *** *** *** *** ***,,Notes:,*** *** *** *** *** *** *** *** ***,*** *** *** *** *** *** *** *** ***"; + foreach (string file in files) + { + lines = File.ReadAllLines(file); + if (lines.Length < 1) + continue; + circularReference = false; + fileNameWithoutExtension = Path.GetFileNameWithoutExtension(file); + for (int i = 0; i < lines.Length; i++) + { + if (!lines[i].Contains($"[[{fileNameWithoutExtension}]]")) + continue; + lines[i] = lines[i].Replace("[[", "__").Replace("]]", "__"); + if (!circularReference) + circularReference = true; + } + if (circularReference) + File.WriteAllLines(file, lines); + lines[0] = string.Empty; + check = string.Join(',', lines); + if (check != match) + continue; + fileDirectory = Path.GetDirectoryName(file); + if (string.IsNullOrEmpty(fileDirectory)) + continue; + checkDirectory = $"{altDrive}:/{ticks}/{fileDirectory[3..]}"; + if (!Directory.Exists(checkDirectory)) + _ = Directory.CreateDirectory(checkDirectory); + checkFile = $"{altDrive}:/{ticks}/{file[3..]}"; + if (File.Exists(checkFile)) + continue; + File.Move(file, checkFile); + } + } + + private static void CreateDailyNotes(string argsZero, long ticks) + { + string file; + string directory; + string weekOfYear; + DateTime dateTime; + string lastDirectory = string.Empty; + DateTime startDateTime = DateTime.Now.AddDays(1); + Calendar calendar = new CultureInfo("en-US").Calendar; + double totalDays = new TimeSpan(DateTime.Now.AddDays(1000).Ticks - startDateTime.Ticks).TotalDays; + int days = (int)Math.Ceiling(totalDays); + for (int i = 0; i < days; i++) + { + dateTime = startDateTime.AddDays(i); + weekOfYear = calendar.GetWeekOfYear(dateTime, CalendarWeekRule.FirstDay, DayOfWeek.Sunday).ToString("00"); + directory = Path.Combine(argsZero, ticks.ToString(), dateTime.ToString("yyyy"), $"Week_{weekOfYear}"); + if (!Directory.Exists(directory)) + _ = Directory.CreateDirectory(directory); + file = string.Concat(Path.Combine(directory, $"{dateTime:yyyy-MM-dd}.md")); + if (File.Exists(file)) + continue; + File.WriteAllLines(file, new string[] + { + "---", + "type: daily-note", + $"created: {dateTime:yyyy-MM-dd}", + "---", + string.Empty, + $"# {dateTime:yyyy-MM-dd dddd}", + string.Empty, + "```bash", + string.Empty, + "```", + }); + if (directory != lastDirectory) + { + Directory.SetCreationTime(directory, dateTime); + Directory.SetLastWriteTime(directory, dateTime); + } + lastDirectory = directory; + } + } + + private static void CreateImportFiles(long ticks, List importFiles) + { + bool csv; + bool tsv; + string file; + string text; + string type; + string title; + string? tags; + string? links; + string[] lines; + int bodyKey = 5; + int tagsKey = 3; + int typeKey = 0; + string fileName; + string tagsText; + int linksKey = 4; + int titleKey = 1; + string linksText; + string[] columns; + string? directory; + string? attributes; + int descriptionKey = 2; + string[]? headerColumns; + string destinationDirectory; + List allLines = new(); + DateTime dateTime = new(ticks); + string csvHeader = "type,title,description,tags,links,body"; + string tsvHeader = "type\ttitle\tdescription\ttags\tlinks\tbody"; + int expectedCount = csvHeader.Length - csvHeader.Replace(",", string.Empty).Length + 1; + foreach (string importFile in importFiles) + { + csv = false; + tsv = false; + headerColumns = null; + directory = Path.GetDirectoryName(importFile); + if (directory is null) + continue; + lines = File.ReadAllLines(importFile); + for (int i = 0; i < lines.Length; i++) + { + if (i == 0) + { + if (lines[i].StartsWith(csvHeader)) + { + (csv, tsv) = (true, false); + headerColumns = lines[i].Split(','); + } + else if (lines[i].StartsWith(tsvHeader)) + { + (csv, tsv) = (false, true); + headerColumns = lines[i].Split('\t'); + } + else + break; + continue; + } + if (csv) + columns = lines[i].Split(','); + else if (tsv) + columns = lines[i].Split('\t'); + else + continue; + if (columns.Length < expectedCount) + continue; + title = columns[titleKey].Trim(); + tagsText = columns[tagsKey].Trim(); + linksText = columns[linksKey].Trim(); + fileName = AlphaNumOnly().Replace(title.ToLower(), "-").Replace("--", "-"); + type = AlphaNumOnly().Replace(columns[typeKey].Trim().ToLower(), "-").Replace("--", "-"); + tags = GetTags(tagsText); + links = GetLinks(type, linksText); + attributes = GetAttributes(columns, headerColumns, expectedCount); + destinationDirectory = Path.Combine(directory, type); + if (!Directory.Exists(destinationDirectory)) + _ = Directory.CreateDirectory(destinationDirectory); + file = Path.Combine(destinationDirectory, $"{fileName}.md"); + allLines.Clear(); + allLines.Add("---"); + allLines.Add($"type: \"{type}\""); + allLines.Add($"title: \"{title}\""); + allLines.Add($"description: \"{columns[descriptionKey].Trim()}\""); + allLines.Add($"created: \"{dateTime:yyyy-MM-ddTHH:mm:ss.fffZ}\""); + allLines.Add($"updated: \"{dateTime:yyyy-MM-ddTHH:mm:ss.fffZ}\""); + if (!string.IsNullOrEmpty(tags)) + allLines.Add(tags); + if (!string.IsNullOrEmpty(attributes)) + allLines.Add(attributes); + allLines.Add("---"); + allLines.Add(string.Empty); + allLines.Add($"# {title}"); + allLines.Add(string.Empty); + if (!string.IsNullOrEmpty(links)) + allLines.Add(links); + allLines.Add(string.Empty); + allLines.Add($"## Comment {dateTime:yyyy-MM-dd}"); + allLines.Add(string.Empty); + allLines.Add(columns[bodyKey].Trim()); + allLines.Add(string.Empty); + text = string.Join(Environment.NewLine, allLines); + File.WriteAllText(file, text); + } + } + } + + internal static void CreateNoteFiles(string argsZero) + { + long ticks = DateTime.Now.Ticks; + List importFiles = new(); + CleanExistingFiles(argsZero, ticks); + importFiles.AddRange(Directory.GetFiles(argsZero, "*.csv", SearchOption.TopDirectoryOnly)); + importFiles.AddRange(Directory.GetFiles(argsZero, "*.tsv", SearchOption.TopDirectoryOnly)); + if (!importFiles.Any()) + CreateDailyNotes(argsZero, ticks); + else + CreateImportFiles(ticks, importFiles); + } + +} \ No newline at end of file diff --git a/Models/AppSettings.cs b/Models/AppSettings.cs new file mode 100644 index 0000000..552225b --- /dev/null +++ b/Models/AppSettings.cs @@ -0,0 +1,26 @@ +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace File_Watcher.Models; + +public record AppSettings(string BuildNumber, + string Company, + string Destination, + string GitCommitSeven, + int MillisecondsDelay, + string WatchDirectory) +{ + + public override string ToString() + { + string result = JsonSerializer.Serialize(this, AppSettingsSourceGenerationContext.Default.AppSettings); + return result; + } + +} + +[JsonSourceGenerationOptions(WriteIndented = true)] +[JsonSerializable(typeof(AppSettings))] +internal partial class AppSettingsSourceGenerationContext : JsonSerializerContext +{ +} \ No newline at end of file diff --git a/Models/Binder/.editorconfig b/Models/Binder/.editorconfig new file mode 100644 index 0000000..1c444cd --- /dev/null +++ b/Models/Binder/.editorconfig @@ -0,0 +1,2 @@ +[*.cs] +csharp_preserve_single_line_statements = true \ No newline at end of file diff --git a/Models/Binder/AppSettings.cs b/Models/Binder/AppSettings.cs new file mode 100644 index 0000000..9f45651 --- /dev/null +++ b/Models/Binder/AppSettings.cs @@ -0,0 +1,57 @@ +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace File_Watcher.Models.Binder; + +public class AppSettings +{ + + public string? BuildNumber { get; set; } + public string? Company { get; set; } + public string? Destination { get; set; } + public string? GitCommitSeven { get; set; } + public int? MillisecondsDelay { get; set; } + public string? WatchDirectory { get; set; } + + public override string ToString() + { + string result = JsonSerializer.Serialize(this, BinderAppSettingsSourceGenerationContext.Default.AppSettings); + return result; + } + + private static Models.AppSettings Get(AppSettings? appSettings) + { + Models.AppSettings result; + if (appSettings is null) throw new NullReferenceException(nameof(appSettings)); + if (appSettings.BuildNumber is null) throw new NullReferenceException(nameof(BuildNumber)); + if (appSettings.Company is null) throw new NullReferenceException(nameof(Company)); + if (appSettings.Destination is null) throw new NullReferenceException(nameof(Destination)); + if (appSettings.GitCommitSeven is null) throw new NullReferenceException(nameof(GitCommitSeven)); + if (appSettings.MillisecondsDelay is null) throw new NullReferenceException(nameof(MillisecondsDelay)); + if (appSettings.WatchDirectory is null) throw new NullReferenceException(nameof(WatchDirectory)); + result = new(appSettings.BuildNumber, + appSettings.Company, + appSettings.Destination, + appSettings.GitCommitSeven, + appSettings.MillisecondsDelay.Value, + appSettings.WatchDirectory); + return result; + } + + public static Models.AppSettings Get(IConfiguration configuration) + { + Models.AppSettings result; +#pragma warning disable IL3050, IL2026 + AppSettings? appSettings = configuration.Get(); +#pragma warning restore IL3050, IL2026 + result = Get(appSettings); + return result; + } + +} + +[JsonSourceGenerationOptions(WriteIndented = true)] +[JsonSerializable(typeof(AppSettings))] +internal partial class BinderAppSettingsSourceGenerationContext : JsonSerializerContext +{ +} \ No newline at end of file diff --git a/Program.cs b/Program.cs new file mode 100644 index 0000000..c0f0ba9 --- /dev/null +++ b/Program.cs @@ -0,0 +1,58 @@ +using File_Watcher.Models; +using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.Hosting.WindowsServices; + +namespace File_Watcher; + +public class Program +{ + + internal static async Task Main(string[] args) + { + ILogger? logger = null; +#pragma warning disable IL3050 + WebApplicationBuilder webApplicationBuilder = WebApplication.CreateBuilder(args); +#pragma warning restore IL3050 + _ = webApplicationBuilder.Configuration.AddUserSecrets(); + AppSettings appSettings = Models.Binder.AppSettings.Get(webApplicationBuilder.Configuration); + if (string.IsNullOrEmpty(appSettings.Company)) + throw new Exception("Company name must have a value!"); + try + { + List collection = new(); + _ = webApplicationBuilder.Services.AddHostedService(); + _ = webApplicationBuilder.Services.AddSingleton(collection); + _ = webApplicationBuilder.Services.AddSingleton(appSettings); + if (WindowsServiceHelpers.IsWindowsService()) + { + collection.Add(nameof(WindowsServiceLifetime)); + _ = webApplicationBuilder.Services.AddSingleton(); + _ = webApplicationBuilder.Logging.AddEventLog(settings => + { +#pragma warning disable CA1416 + if (string.IsNullOrEmpty(settings.SourceName)) + settings.SourceName = webApplicationBuilder.Environment.ApplicationName; +#pragma warning restore + }); + } + using IHost host = webApplicationBuilder.Build(); + logger = host.Services.GetRequiredService>(); + if (string.IsNullOrEmpty(appSettings.Company)) + { + Environment.ExitCode = -1; + _ = host.StopAsync(); + } + logger.LogInformation("Starting Web Application"); + logger.LogCritical("{Company}", appSettings.Company); + await host.RunAsync(); + } + catch (Exception ex) + { + try + { logger?.LogCritical(ex, "Host terminated unexpectedly"); } + catch (Exception) { } + throw; + } + } + +} \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..e37e4b1 --- /dev/null +++ b/README.md @@ -0,0 +1,20 @@ +# Introduction +TODO: Give a short introduction of your project. Let this section explain the objectives or the motivation behind this project. + +# Getting Started +TODO: Guide users through getting your code up and running on their own system. In this section you can talk about: +1. Installation process +2. Software dependencies +3. Latest releases +4. API references + +# Build and Test +TODO: Describe and show how to build your code and run the tests. + +# Contribute +TODO: Explain how other users and developers can contribute to make your code better. + +If you want to learn more about creating good readme files then refer the following [guidelines](https://docs.microsoft.com/en-us/azure/devops/repos/git/create-a-readme?view=azure-devops). You can also seek inspiration from the below readme files: +- [ASP.NET Core](https://github.com/aspnet/Home) +- [Visual Studio Code](https://github.com/Microsoft/vscode) +- [Chakra Core](https://github.com/Microsoft/ChakraCore) \ No newline at end of file diff --git a/Worker.cs b/Worker.cs new file mode 100644 index 0000000..3f3c7d6 --- /dev/null +++ b/Worker.cs @@ -0,0 +1,78 @@ +using File_Watcher.Models; +using Microsoft.Extensions.Hosting.WindowsServices; + +namespace File_Watcher; + +public partial class Worker : BackgroundService +{ + + private readonly bool _IsWindowsService; + private readonly ILogger _Logger; + private readonly AppSettings _AppSettings; + + public Worker(IServiceProvider serviceProvider, ILogger logger, AppSettings appSettings, List collection) + { + _Logger = logger; + _AppSettings = appSettings; + logger.LogInformation("{buildNumber}-{gitCommitSeven}", _AppSettings.BuildNumber, _AppSettings.GitCommitSeven); + try + { logger.LogInformation("<{folder}>", Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)); } + catch (Exception) { } + _IsWindowsService = collection.Contains(nameof(WindowsServiceLifetime)); + } + + private void Body() + { + _Logger.LogInformation("A) Next execute will be at {date}", DateTime.Now.AddMilliseconds(_AppSettings.MillisecondsDelay).ToString("yyyy-MM-dd hh:mm:ss.fff tt")); + if (!Directory.Exists(_AppSettings.WatchDirectory)) + _ = Directory.CreateDirectory(_AppSettings.WatchDirectory); + if (!Directory.Exists(Path.GetPathRoot(_AppSettings.Destination)) || !Directory.Exists(_AppSettings.Destination)) + _Logger.LogCritical("<{Destination}> Doesn't exist!", _AppSettings.Destination); + else + { + string[] files; + string checkFile; + FileInfo fileInfo; + string checkDirectory; + string[] directories = Directory.GetDirectories(_AppSettings.WatchDirectory, "*", SearchOption.TopDirectoryOnly); + foreach (string directory in directories) + { + checkDirectory = Path.Combine(_AppSettings.Destination, Path.GetFileName(directory)); + try + { + if (!Directory.Exists(checkDirectory)) + _ = Directory.CreateDirectory(checkDirectory); + files = Directory.GetFiles(directory, "*", SearchOption.TopDirectoryOnly); + foreach (string file in files) + { + fileInfo = new(file); + if (new TimeSpan(DateTime.Now.Ticks - fileInfo.LastWriteTime.Ticks).TotalMilliseconds < _AppSettings.MillisecondsDelay) + continue; + checkFile = Path.Combine(checkDirectory, Path.GetFileName(file)); + if (File.Exists(checkFile)) + continue; + try + { File.Move(file, checkFile); } + catch (Exception ex) + { _Logger.LogError(ex, "Inner loop error!"); } + } + } + catch (Exception ex) + { _Logger.LogError(ex, "Loop error!"); } + } + } + _Logger.LogInformation("B) Next execute will be at {date}", DateTime.Now.AddMilliseconds(_AppSettings.MillisecondsDelay).ToString("yyyy-MM-dd hh:mm:ss.fff tt")); + } + + private async Task Body(CancellationToken stoppingToken) + { + while (_IsWindowsService && !stoppingToken.IsCancellationRequested) + { + Body(); + await Task.Delay(_AppSettings.MillisecondsDelay, stoppingToken); + } + } + + protected override async Task ExecuteAsync(CancellationToken stoppingToken) => + await Body(stoppingToken); +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..aed116c --- /dev/null +++ b/package-lock.json @@ -0,0 +1,35 @@ +{ + "name": "File-Folder-Helper", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "devDependencies": { + "prettier": "3.0.0" + } + }, + "node_modules/prettier": { + "version": "3.0.0", + "resolved": "http://localhost:4873/prettier/-/prettier-3.0.0.tgz", + "integrity": "sha512-zBf5eHpwHOGPC47h0zrPyNn+eAEIdEzfywMoYn2XPi0P44Zp0tSq64rq0xAREh4auw2cJZHo9QUob+NqCQky4g==", + "dev": true, + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + } + }, + "dependencies": { + "prettier": { + "version": "3.0.0", + "resolved": "http://localhost:4873/prettier/-/prettier-3.0.0.tgz", + "integrity": "sha512-zBf5eHpwHOGPC47h0zrPyNn+eAEIdEzfywMoYn2XPi0P44Zp0tSq64rq0xAREh4auw2cJZHo9QUob+NqCQky4g==", + "dev": true + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..b7f882a --- /dev/null +++ b/package.json @@ -0,0 +1,10 @@ +{ + "scripts": { + "prettier.check": "prettier . --check", + "prettier.write": "prettier . --write", + "garbage-collect": "git gc" + }, + "devDependencies": { + "prettier": "3.0.0" + } +} \ No newline at end of file