From e2ec4a585747da0e1cb8e33d164c636055137dca Mon Sep 17 00:00:00 2001 From: Sam Therapy Date: Tue, 15 Nov 2022 17:25:54 +0100 Subject: [PATCH] format things, I think also prepare pipelines and stuff Signed-off-by: Sam Therapy --- .drone.yml | 65 +++ .editorconfig | 248 +++++++++ .github/FUNDING.yml | 1 - .github/workflows/dotnet-core.yml | 2 +- .gitignore | 2 + Dockerfile | 9 +- src/BSLManager/App.cs | 78 +-- src/BSLManager/BSLManager.csproj | 4 +- src/BSLManager/Bootstrapper.cs | 40 +- src/BSLManager/Domain/FollowersListState.cs | 18 +- src/BSLManager/Program.cs | 13 +- src/BSLManager/Tools/BasicLogger.cs | 6 +- src/BSLManager/Tools/ConsoleGui.cs | 5 +- src/BSLManager/Tools/SettingsManager.cs | 33 +- .../ApDeserializer.cs | 7 +- .../BirdsiteLive.ActivityPub.csproj | 2 +- .../Converters/ContextArrayConverter.cs | 18 +- .../Converters/UrlFactory.cs | 4 +- .../Models/Activity.cs | 9 +- .../Models/ActivityAccept.cs | 4 +- .../Models/ActivityAcceptFollow.cs | 4 +- .../Models/ActivityAcceptUndoFollow.cs | 4 +- .../Models/ActivityCreate.cs | 9 +- .../Models/ActivityCreateNote.cs | 6 +- .../Models/ActivityFollow.cs | 4 +- .../Models/ActivityRejectFollow.cs | 4 +- .../Models/ActivityUndo.cs | 4 +- .../Models/ActivityUndoFollow.cs | 4 +- src/BirdsiteLive.ActivityPub/Models/Actor.cs | 4 +- .../Models/Attachment.cs | 4 +- .../Models/EndPoints.cs | 4 +- .../Models/Followers.cs | 5 +- src/BirdsiteLive.ActivityPub/Models/Image.cs | 4 +- src/BirdsiteLive.ActivityPub/Models/Note.cs | 11 +- .../Models/PublicKey.cs | 4 +- src/BirdsiteLive.ActivityPub/Models/Tag.cs | 7 +- .../Models/UserAttachment.cs | 4 +- .../Models/WebFingerData.cs | 2 +- .../BirdsiteLive.Common.csproj | 2 +- .../Extensions/EnumerableExt.cs | 4 +- .../Regexes/EmojiRegexes.cs | 9 +- .../Regexes/HashtagRegexes.cs | 8 +- .../Regexes/HeaderRegexes.cs | 4 +- src/BirdsiteLive.Common/Regexes/UrlRegexes.cs | 8 +- .../Regexes/UserRegexes.cs | 8 +- .../Settings/DbSettings.cs | 4 +- .../Settings/InstanceSettings.cs | 2 +- .../Settings/LogsSettings.cs | 4 +- .../Settings/ModerationSettings.cs | 4 +- .../Settings/TwitterSettings.cs | 4 +- src/BirdsiteLive.Common/Structs/DbTypes.cs | 4 +- src/BirdsiteLive.Cryptography/ASN1.cs | 8 +- .../BirdsiteLive.Cryptography.csproj | 2 +- src/BirdsiteLive.Cryptography/MagicKey.cs | 47 +- src/BirdsiteLive.Cryptography/RsaGenerator.cs | 25 +- src/BirdsiteLive.Cryptography/RsaKeys.cs | 55 +- src/BirdsiteLive.Domain/ActivityPubService.cs | 82 ++- .../BirdsiteLive.Domain.csproj | 2 +- .../BusinessUseCases/ProcessFollowUser.cs | 37 +- .../BusinessUseCases/ProcessUnfollowUser.cs | 21 +- src/BirdsiteLive.Domain/CryptoService.cs | 37 +- .../Factories/MagicKeyFactory.cs | 13 +- .../Repository/ModerationRepository.cs | 58 +- .../Repository/PublicationRepository.cs | 9 +- .../Statistics/ExtractionStatisticsHandler.cs | 18 +- src/BirdsiteLive.Domain/StatusService.cs | 61 +- .../Tools/ModerationRegexParser.cs | 6 +- .../Tools/PatternsParser.cs | 15 +- .../Tools/StatusExtractor.cs | 77 ++- src/BirdsiteLive.Domain/UserService.cs | 302 +++++++--- .../Actions/RejectAllFollowingsAction.cs | 11 +- .../Actions/RejectFollowingAction.cs | 7 +- .../Actions/RemoveFollowerAction.cs | 11 +- .../Actions/RemoveTwitterAccountAction.cs | 17 +- .../BirdsiteLive.Moderation.csproj | 2 +- .../ModerationPipeline.cs | 25 +- .../Processors/FollowerModerationProcessor.cs | 30 +- .../TwitterAccountModerationProcessor.cs | 31 +- .../BirdsiteLive.Pipeline.csproj | 4 +- .../IRefreshTwitterUserStatusProcessor.cs | 10 +- .../Contracts/IRetrieveFollowersProcessor.cs | 10 +- .../Contracts/IRetrieveTweetsProcessor.cs | 10 +- .../IRetrieveTwitterUsersProcessor.cs | 10 +- .../Contracts/ISaveProgressionProcessor.cs | 5 +- .../ISendTweetsToFollowersProcessor.cs | 10 +- .../Models/UserWithDataToSync.cs | 5 +- .../RefreshTwitterUserStatusProcessor.cs | 22 +- .../Processors/RetrieveFollowersProcessor.cs | 10 +- .../Processors/RetrieveTweetsProcessor.cs | 50 +- .../RetrieveTwitterUsersProcessor.cs | 25 +- .../Processors/SaveProgressionProcessor.cs | 45 +- .../SendTweetsToFollowersProcessor.cs | 66 ++- .../SubTasks/SendTweetsToInboxTask.cs | 59 +- .../SubTasks/SendTweetsToSharedInboxTask.cs | 63 ++- .../StatusPublicationPipeline.cs | 132 ++++- .../Tools/MaxUsersNumberProvider.cs | 22 +- .../BirdsiteLive.Twitter.csproj | 2 +- .../CachedTwitterTweetService.cs | 21 +- .../CachedTwitterUserService.cs | 18 +- .../Extractors/TweetExtractor.cs | 72 ++- .../Models/ApiStatistics.cs | 4 +- .../Models/ExtractedMedia.cs | 4 +- .../Models/ExtractedTweet.cs | 4 +- .../Models/TwitterUser.cs | 4 +- .../Statistics/TwitterStatisticsHandler.cs | 25 +- .../Tools/TwitterAuthenticationInitializer.cs | 28 +- .../TwitterTweetsService.cs | 27 +- .../TwitterUserService.cs | 19 +- src/BirdsiteLive.sln | 2 +- src/BirdsiteLive/BirdsiteLive.csproj | 4 +- .../Component/NodeInfoViewComponent.cs | 31 +- .../Controllers/AboutController.cs | 6 +- .../Controllers/DebugingController.cs | 24 +- .../Controllers/HomeController.cs | 17 +- .../Controllers/InboxController.cs | 6 +- .../Controllers/StatisticsController.cs | 11 +- .../Controllers/UsersController.cs | 140 +++-- .../Controllers/WellKnownController.cs | 66 +-- src/BirdsiteLive/Models/DisplayTwitterUser.cs | 4 +- .../Models/StatisticsModels/Statistics.cs | 4 +- .../Models/WellKnownModels/Link.cs | 4 +- .../Models/WellKnownModels/Metadata.cs | 4 +- .../Models/WellKnownModels/NodeInfoV20.cs | 4 +- .../Models/WellKnownModels/NodeInfoV21.cs | 4 +- .../Models/WellKnownModels/Services.cs | 4 +- .../Models/WellKnownModels/Software.cs | 4 +- .../Models/WellKnownModels/SoftwareV21.cs | 4 +- .../Models/WellKnownModels/Usage.cs | 4 +- .../Models/WellKnownModels/Users.cs | 4 +- .../Models/WellKnownModels/WebFingerLink.cs | 4 +- .../Models/WellKnownModels/WebFingerResult.cs | 4 +- .../WellKnownModels/WellKnownNodeInfo.cs | 4 +- src/BirdsiteLive/Program.cs | 12 +- src/BirdsiteLive/Services/AboutPageService.cs | 35 +- .../Services/FederationService.cs | 13 +- src/BirdsiteLive/Startup.cs | 43 +- src/BirdsiteLive/Views/Debuging/Index.cshtml | 2 +- src/BirdsiteLive/Views/Home/Privacy.cshtml | 2 +- .../Shared/Components/NodeInfo/Default.cshtml | 2 +- src/BirdsiteLive/Views/Shared/Error.cshtml | 2 +- src/BirdsiteLive/Views/Shared/_Layout.cshtml | 2 +- .../Shared/_ValidationScriptsPartial.cshtml | 2 +- .../Views/Statistics/Index.cshtml | 2 +- src/BirdsiteLive/Views/Users/Index.cshtml | 2 +- src/BirdsiteLive/Views/Users/Tweet.cshtml | 2 +- .../Views/Users/UserNotFound.cshtml | 2 +- src/BirdsiteLive/Views/_ViewImports.cshtml | 2 +- src/BirdsiteLive/Views/_ViewStart.cshtml | 2 +- src/BirdsiteLive/wwwroot/css/birdsite.css | 2 +- src/BirdsiteLive/wwwroot/css/pattern.css | 2 +- src/BirdsiteLive/wwwroot/css/site.css | 2 +- src/BirdsiteLive/wwwroot/js/site.js | 2 +- .../BirdsiteLive.DAL.Postgres.csproj | 4 +- .../DataAccessLayers/Base/PostgresBase.cs | 10 +- .../CachedTweetsPostgresDal.cs | 35 +- .../DbInitializerPostgresDal.cs | 67 ++- .../DataAccessLayers/FollowersPostgresDal.cs | 104 +++- .../TwitterUserPostgresDal.cs | 91 ++- .../Settings/PostgresSettings.cs | 4 +- .../Tools/PostgresTools.cs | 6 +- .../BirdsiteLive.DAL/BirdsiteLive.DAL.csproj | 2 +- .../Contracts/ICachedTweetsDal.cs | 6 +- .../Contracts/IDbInitializerDal.cs | 6 +- .../Contracts/IFollowersDal.cs | 16 +- .../Contracts/ITwitterUserDal.cs | 13 +- .../BirdsiteLive.DAL/DatabaseInitializer.cs | 16 +- .../BirdsiteLive.DAL/Models/CachedTweet.cs | 5 +- .../BirdsiteLive.DAL/Models/Follower.cs | 6 +- .../Models/SyncTwitterUser.cs | 4 +- .../BirdsiteLive.DAL/Tools/RandomGenerator.cs | 10 +- .../BSLManager.Tests/BSLManager.Tests.csproj | 2 +- .../Domain/FollowersListStateTests.cs | 9 +- .../ActivityTests.cs | 1 + .../ActorTests.cs | 16 +- .../ApDeserializerTests.cs | 27 +- .../BirdsiteLive.ActivityPub.Tests.csproj | 2 +- .../BirdsiteLive.Common.Tests.csproj | 2 +- .../Regexes/HeaderRegexTests.cs | 14 +- .../BirdsiteLive.Cryptography.Tests.csproj | 2 +- .../MagicKeyTests.cs | 6 +- .../RsaKeysTests.cs | 4 +- .../BirdsiteLive.DAL.Postgres.Tests.csproj | 2 +- .../Base/PostgresTestingBase.cs | 9 +- .../CachedTweetsPostgresDalTests.cs | 6 +- .../DbInitializerPostgresDalTests.cs | 8 +- .../FollowersPostgresDalTests.cs | 312 ++++++++--- .../TwitterUserPostgresDalTests.cs | 32 +- .../BirdsiteLive.DAL.Tests.csproj | 2 +- .../DatabaseInitializerTests.cs | 122 ++-- .../BirdsiteLive.Domain.Tests.csproj | 2 +- .../ProcessFollowUserTests.cs | 70 ++- .../ProcessUnfollowUserTests.cs | 68 ++- .../Repository/ModerationRepositoryTests.cs | 240 +++++--- .../StatusServiceTests.cs | 51 +- .../Tools/ModerationRegexParserTests.cs | 10 +- .../Tools/PatternsParserTests.cs | 6 +- .../Tools/StatusExtractorTests.cs | 242 ++++++-- .../Actions/RejectAllFollowingsActionTests.cs | 79 ++- .../Actions/RejectFollowingActionTests.cs | 61 +- .../Actions/RemoveFollowerActionTests.cs | 55 +- .../RemoveTwitterAccountActionTests.cs | 86 +-- .../BirdsiteLive.Moderation.Tests.csproj | 2 +- .../ModerationPipelineTests.cs | 65 ++- .../FollowerModerationProcessorTests.cs | 116 ++-- .../TwitterAccountModerationProcessorTests.cs | 143 +++-- .../BirdsiteLive.Pipeline.Tests.csproj | 2 +- .../RefreshTwitterUserStatusProcessorTests.cs | 236 ++++---- .../RetrieveFollowersProcessorTests.cs | 33 +- .../RetrieveTweetsProcessorTests.cs | 151 +++-- .../RetrieveTwitterUsersProcessorTests.cs | 70 ++- .../SaveProgressionProcessorTests.cs | 185 +++---- .../SendTweetsToFollowersProcessorTests.cs | 521 ++++++++++-------- .../SubTasks/SendTweetsToInboxTaskTests.cs | 469 +++++++++------- .../SubTasks/SendTweetsToSharedInboxTests.cs | 481 +++++++++------- .../StatusPublicationPipelineTests.cs | 43 +- .../Tools/MaxUsersNumberProviderTests.cs | 33 +- 216 files changed, 4832 insertions(+), 2685 deletions(-) create mode 100644 .drone.yml create mode 100644 .editorconfig delete mode 100644 .github/FUNDING.yml diff --git a/.drone.yml b/.drone.yml new file mode 100644 index 0000000..59261de --- /dev/null +++ b/.drone.yml @@ -0,0 +1,65 @@ +kind: pipeline +name: testing +type: docker + +steps: + - name: Install Dependencies + image: mcr.microsoft.com/dotnet/sdk:6.0 + commands: + - dotnet restore ./src + + - name: Build + image: mcr.microsoft.com/dotnet/sdk:6.0 + commands: + - dotnet build --configuration Release --no-restore ./src + - name: Test + image: mcr.microsoft.com/dotnet/sdk:6.0 + commands: + - sed -i "s/127\.0\.0\.1/database/g" ./src/Tests/BirdsiteLive.DAL.Postgres.Tests/DataAccessLayers/Base/PostgresTestingBase.cs + - dotnet test --no-restore --verbosity minimal ./src + +services: + - name: database + image: postgres:15 + environment: + POSTGRES_USER: birdtest + POSTGRES_PASSWORD: mysecretpassword + POSTGRES_DB: birdsitetest + +--- + +kind: pipeline +name: docker-publish +type: docker + +depends_on: + - testing + +steps: + - name: Build + image: plugins/docker + settings: + repo: git.froth.zone/sam/BirdsiteLIVE + dry_run: true + when: + event: + - pull_request + depends_on: + - "clone" + + - name: Build & Publish + image: plugins/docker + settings: + registry: git.froth.zone + username: sam + password: + from_secret: password + repo: git.froth.zone/sam/BirdsiteLIVE + tags: latest + when: + branch: + - master + event: + - push + depends_on: + - "clone" \ No newline at end of file diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..0780de1 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,248 @@ +# Remove the line below if you want to inherit .editorconfig settings from higher directories +root = true + +# C# files +[*.cs] + +#### Core EditorConfig Options #### + +# Indentation and spacing +indent_size = 4 +indent_style = space +tab_width = 4 + +# New line preferences +end_of_line = lf +insert_final_newline = true + +#### .NET Coding Conventions #### + +# Organize usings +dotnet_separate_import_directive_groups = true +dotnet_sort_system_directives_first = true +file_header_template = unset + +# this. and Me. preferences +dotnet_style_qualification_for_event = false +dotnet_style_qualification_for_field = false +dotnet_style_qualification_for_method = false +dotnet_style_qualification_for_property = false + +# Language keywords vs BCL types preferences +dotnet_style_predefined_type_for_locals_parameters_members = true +dotnet_style_predefined_type_for_member_access = true + +# Parentheses preferences +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 + +# Modifier preferences +dotnet_style_require_accessibility_modifiers = for_non_interface_members + +# Expression-level preferences +dotnet_style_coalesce_expression = true +dotnet_style_collection_initializer = true +dotnet_style_explicit_tuple_names = true +dotnet_style_namespace_match_folder = false +dotnet_style_null_propagation = true +dotnet_style_object_initializer = true +dotnet_style_operator_placement_when_wrapping = beginning_of_line +dotnet_style_prefer_auto_properties = true +dotnet_style_prefer_compound_assignment = true +dotnet_style_prefer_conditional_expression_over_assignment = true +dotnet_style_prefer_conditional_expression_over_return = true +dotnet_style_prefer_foreach_explicit_cast_in_source = when_strongly_typed +dotnet_style_prefer_inferred_anonymous_type_member_names = true +dotnet_style_prefer_inferred_tuple_names = true +dotnet_style_prefer_is_null_check_over_reference_equality_method = true +dotnet_style_prefer_simplified_boolean_expressions = true +dotnet_style_prefer_simplified_interpolation = true + +# Field preferences +dotnet_style_readonly_field = true + +# Parameter preferences +dotnet_code_quality_unused_parameters = all + +# Suppression preferences +dotnet_remove_unnecessary_suppression_exclusions = none + +# New line preferences +dotnet_style_allow_multiple_blank_lines_experimental = false +dotnet_style_allow_statement_immediately_after_block_experimental = false + +#### C# Coding Conventions #### + +# var preferences +csharp_style_var_elsewhere = true +csharp_style_var_for_built_in_types = false +csharp_style_var_when_type_is_apparent = true + +# Expression-bodied members +csharp_style_expression_bodied_accessors = true:silent +csharp_style_expression_bodied_constructors = when_on_single_line:silent +csharp_style_expression_bodied_indexers = true:silent +csharp_style_expression_bodied_lambdas = true:silent +csharp_style_expression_bodied_local_functions = when_on_single_line:silent +csharp_style_expression_bodied_methods = when_on_single_line:silent +csharp_style_expression_bodied_operators = when_on_single_line:silent +csharp_style_expression_bodied_properties = true:silent + +# Pattern matching preferences +csharp_style_pattern_matching_over_as_with_null_check = true +csharp_style_pattern_matching_over_is_with_cast_check = true +csharp_style_prefer_extended_property_pattern = true +csharp_style_prefer_not_pattern = true +csharp_style_prefer_pattern_matching = true +csharp_style_prefer_switch_expression = true:suggestion + +# Null-checking preferences +csharp_style_conditional_delegate_call = true + +# Modifier preferences +csharp_prefer_static_local_function = true +csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,required,volatile,async + +# Code-block preferences +csharp_prefer_braces = when_multiline:silent +csharp_prefer_simple_using_statement = true:suggestion +csharp_style_namespace_declarations = file_scoped:suggestion +csharp_style_prefer_method_group_conversion = true:silent +csharp_style_prefer_top_level_statements = true:suggestion + +# Expression-level preferences +csharp_prefer_simple_default_expression = true:suggestion +csharp_style_deconstructed_variable_declaration = true:suggestion +csharp_style_implicit_object_creation_when_type_is_apparent = true:suggestion +csharp_style_inlined_variable_declaration = true:suggestion +csharp_style_prefer_index_operator = true:suggestion +csharp_style_prefer_local_over_anonymous_function = true:suggestion +csharp_style_prefer_null_check_over_type_check = true:suggestion +csharp_style_prefer_range_operator = true:suggestion +csharp_style_prefer_tuple_swap = true:suggestion +csharp_style_prefer_utf8_string_literals = true:suggestion +csharp_style_throw_expression = true:suggestion +csharp_style_unused_value_assignment_preference = discard_variable:suggestion +csharp_style_unused_value_expression_statement_preference = discard_variable:silent + +# 'using' directive preferences +csharp_using_directive_placement = outside_namespace:silent + +# New line preferences +csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = false +csharp_style_allow_blank_lines_between_consecutive_braces_experimental = false +csharp_style_allow_embedded_statements_on_same_line_experimental = true + +#### C# Formatting Rules #### + +# New line preferences +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 + +# Indentation preferences +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 + +# Space preferences +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 + +# Wrapping preferences +csharp_preserve_single_line_blocks = true +csharp_preserve_single_line_statements = true + +#### Naming styles #### + +# Naming rules + +dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion +dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface +dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i + +dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.types_should_be_pascal_case.symbols = types +dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case + +dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members +dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case + +# Symbol specifications + +dotnet_naming_symbols.interface.applicable_kinds = interface +dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.interface.required_modifiers = + +dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum +dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.types.required_modifiers = + +dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method +dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.non_field_members.required_modifiers = + +# Naming styles + +dotnet_naming_style.pascal_case.required_prefix = +dotnet_naming_style.pascal_case.required_suffix = +dotnet_naming_style.pascal_case.word_separator = +dotnet_naming_style.pascal_case.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.begins_with_i.capitalization = pascal_case +dotnet_diagnostic.IDE0004.severity = suggestion +dotnet_diagnostic.IDE0005.severity = suggestion + +[*.{cs,vb}] +dotnet_style_coalesce_expression = true:suggestion +dotnet_style_null_propagation = true:suggestion +dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion +dotnet_style_prefer_auto_properties = true:silent +dotnet_style_object_initializer = true:suggestion +dotnet_style_collection_initializer = true:suggestion +dotnet_style_prefer_simplified_boolean_expressions = true:suggestion +dotnet_style_operator_placement_when_wrapping = beginning_of_line +tab_width = 4 +indent_size = 4 +end_of_line = crlf +dotnet_style_prefer_conditional_expression_over_assignment = true:silent +dotnet_style_namespace_match_folder = false:silent +dotnet_style_explicit_tuple_names = true:suggestion +dotnet_style_prefer_conditional_expression_over_return = true:silent +dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion +dotnet_style_prefer_inferred_tuple_names = true:suggestion +dotnet_style_prefer_simplified_interpolation = true:suggestion +dotnet_style_prefer_compound_assignment = true:suggestion \ No newline at end of file diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml deleted file mode 100644 index 4421d97..0000000 --- a/.github/FUNDING.yml +++ /dev/null @@ -1 +0,0 @@ -patreon: nicolasconstant diff --git a/.github/workflows/dotnet-core.yml b/.github/workflows/dotnet-core.yml index d28cb08..1d4d0ba 100644 --- a/.github/workflows/dotnet-core.yml +++ b/.github/workflows/dotnet-core.yml @@ -12,7 +12,7 @@ jobs: steps: - uses: actions/checkout@v2 - name: Launch Db for testing - run: docker run --name postgres -e POSTGRES_DB=mytestdb -e POSTGRES_PASSWORD=mysecretpassword -d -p 5432:5432 postgres + run: docker run --name postgres -e POSTGRES_USER=birdtest -e POSTGRES_DB=birdsitetest -e POSTGRES_PASSWORD=mysecretpassword -d -p 5432:5432 postgres - name: Setup .NET Core uses: actions/setup-dotnet@v1 with: diff --git a/.gitignore b/.gitignore index a6584fc..28aa329 100644 --- a/.gitignore +++ b/.gitignore @@ -352,3 +352,5 @@ MigrationBackup/ # Ionide (cross platform F# VS Code tools) working folder .ionide/ /src/BSLManager/Properties/launchSettings.json + +.dccache \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 11a4422..9c6cd2a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,14 +1,15 @@ #See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging. -FROM mcr.microsoft.com/dotnet/aspnet:3.1-buster-slim AS base +FROM mcr.microsoft.com/dotnet/aspnet:6.0-slim AS base WORKDIR /app EXPOSE 80 EXPOSE 443 -FROM mcr.microsoft.com/dotnet/sdk:3.1-buster AS publish +FROM mcr.microsoft.com/dotnet/sdk:6.0 AS publish +WORKDIR / COPY ./src/ ./src/ -RUN dotnet publish "/src/BirdsiteLive/BirdsiteLive.csproj" -c Release -o /app/publish -RUN dotnet publish "/src/BSLManager/BSLManager.csproj" -r linux-x64 --self-contained true -p:PublishSingleFile=true -p:IncludeAllContentForSelfExtract=true -c Release -o /app/publish +RUN dotnet publish "/src/BirdsiteLive/BirdsiteLive.csproj" -c Release -o /app/publish \ + && dotnet publish "/src/BSLManager/BSLManager.csproj" -r linux-x64 --self-contained true -p:PublishSingleFile=true -p:IncludeAllContentForSelfExtract=true -c Release -o /app/publish FROM base AS final WORKDIR /app diff --git a/src/BSLManager/App.cs b/src/BSLManager/App.cs index 37697cc..a0aa79f 100644 --- a/src/BSLManager/App.cs +++ b/src/BSLManager/App.cs @@ -1,13 +1,16 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Threading.Tasks; + using BirdsiteLive.DAL.Contracts; using BirdsiteLive.DAL.Models; using BirdsiteLive.Moderation.Actions; + using BSLManager.Domain; using BSLManager.Tools; + using Terminal.Gui; namespace BSLManager @@ -37,7 +40,6 @@ namespace BSLManager { X = 0, Y = 1, // Leave one row for the toplevel menu - // By using Dim.Fill(), it will automatically resize without manual intervention Width = Dim.Fill(), Height = Dim.Fill() @@ -46,29 +48,46 @@ namespace BSLManager top.Add(win); // Creates a menubar, the item "New" has a help menu. - var menu = new MenuBar(new MenuBarItem[] - { - new MenuBarItem("_File", new MenuItem[] + var menu = new MenuBar( + new MenuBarItem[] { - new MenuItem("_Quit", "", () => - { - if (Quit()) top.Running = false; - }) - }), - //new MenuBarItem ("_Edit", new MenuItem [] { - // new MenuItem ("_Copy", "", null), - // new MenuItem ("C_ut", "", null), - // new MenuItem ("_Paste", "", null) - //}) - }); + new MenuBarItem( + "_File", + new MenuItem[] + { + new MenuItem( + "_Quit", + "", + () => + { + if (Quit()) + top.Running = false; + } + ) + } + ), + //new MenuBarItem ("_Edit", new MenuItem [] { + // new MenuItem ("_Copy", "", null), + // new MenuItem ("C_ut", "", null), + // new MenuItem ("_Paste", "", null) + //}) + } + ); top.Add(menu); static bool Quit() { - var n = MessageBox.Query(50, 7, "Quit BSL Manager", "Are you sure you want to quit?", "Yes", "No"); + var n = MessageBox.Query( + 50, + 7, + "Quit BSL Manager", + "Are you sure you want to quit?", + "Yes", + "No" + ); return n == 0; } - + RetrieveUserList(); var list = new ListView(_state.GetDisplayableList()) @@ -84,11 +103,13 @@ namespace BSLManager if (_.KeyEvent.Key == Key.Enter) { OpenFollowerDialog(list.SelectedItem); - } - else if (_.KeyEvent.Key == Key.Delete - || _.KeyEvent.Key == Key.DeleteChar - || _.KeyEvent.Key == Key.Backspace - || _.KeyEvent.Key == Key.D) + } + else if ( + _.KeyEvent.Key == Key.Delete + || _.KeyEvent.Key == Key.DeleteChar + || _.KeyEvent.Key == Key.Backspace + || _.KeyEvent.Key == Key.D + ) { OpenDeleteDialog(list.SelectedItem); } @@ -113,12 +134,7 @@ namespace BSLManager } }; - win.Add( - listingFollowersLabel, - filterLabel, - filterText, - list - ); + win.Add(listingFollowersLabel, filterLabel, filterText, list); Application.Run(); } @@ -224,7 +240,7 @@ namespace BSLManager try { var userToDelete = _state.GetElementAt(el); - + BasicLogger.Log($"Delete {userToDelete.Acct}@{userToDelete.Host}"); await _removeFollowerAction.ProcessAsync(userToDelete); BasicLogger.Log($"Remove user from list"); @@ -249,4 +265,4 @@ namespace BSLManager }); } } -} \ No newline at end of file +} diff --git a/src/BSLManager/BSLManager.csproj b/src/BSLManager/BSLManager.csproj index 52e5cde..5daddfc 100644 --- a/src/BSLManager/BSLManager.csproj +++ b/src/BSLManager/BSLManager.csproj @@ -1,8 +1,8 @@ - + Exe - netcoreapp3.1 + net6.0 diff --git a/src/BSLManager/Bootstrapper.cs b/src/BSLManager/Bootstrapper.cs index 7375cd6..a7cef29 100644 --- a/src/BSLManager/Bootstrapper.cs +++ b/src/BSLManager/Bootstrapper.cs @@ -1,12 +1,15 @@ -using System; +using System; using System.Net.Http; + using BirdsiteLive.Common.Settings; using BirdsiteLive.Common.Structs; using BirdsiteLive.DAL.Contracts; using BirdsiteLive.DAL.Postgres.DataAccessLayers; using BirdsiteLive.DAL.Postgres.Settings; + using Lamar; using Lamar.Scanning.Conventions; + using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; @@ -33,13 +36,17 @@ namespace BSLManager x.For().Use(x => _instanceSettings); - if (string.Equals(_dbSettings.Type, DbTypes.Postgres, StringComparison.OrdinalIgnoreCase)) + if ( + string.Equals( + _dbSettings.Type, + DbTypes.Postgres, + StringComparison.OrdinalIgnoreCase + ) + ) { - var connString = $"Host={_dbSettings.Host};Username={_dbSettings.User};Password={_dbSettings.Password};Database={_dbSettings.Name}"; - var postgresSettings = new PostgresSettings - { - ConnString = connString - }; + var connString = + $"Host={_dbSettings.Host};Username={_dbSettings.User};Password={_dbSettings.Password};Database={_dbSettings.Name}"; + var postgresSettings = new PostgresSettings { ConnString = connString }; x.For().Use(x => postgresSettings); x.For().Use().Singleton(); @@ -51,8 +58,11 @@ namespace BSLManager throw new NotImplementedException($"{_dbSettings.Type} is not supported"); } - var serviceProvider = new ServiceCollection().AddHttpClient().BuildServiceProvider(); - x.For().Use(_ => serviceProvider.GetService()); + var serviceProvider = new ServiceCollection() + .AddHttpClient() + .BuildServiceProvider(); + x.For() + .Use(_ => serviceProvider.GetService()); x.For(typeof(ILogger<>)).Use(typeof(DummyLogger<>)); @@ -76,9 +86,13 @@ namespace BSLManager public class DummyLogger : ILogger { - public void Log(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func formatter) - { - } + public void Log( + LogLevel logLevel, + EventId eventId, + TState state, + Exception exception, + Func formatter + ) { } public bool IsEnabled(LogLevel logLevel) { @@ -91,4 +105,4 @@ namespace BSLManager } } } -} \ No newline at end of file +} diff --git a/src/BSLManager/Domain/FollowersListState.cs b/src/BSLManager/Domain/FollowersListState.cs index 02c2151..880e8df 100644 --- a/src/BSLManager/Domain/FollowersListState.cs +++ b/src/BSLManager/Domain/FollowersListState.cs @@ -1,5 +1,6 @@ -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; + using BirdsiteLive.DAL.Models; namespace BSLManager.Domain @@ -10,11 +11,11 @@ namespace BSLManager.Domain private List _sourceUserList = new List(); private List _filteredSourceUserList = new List(); - + public void Load(List followers) { _sourceUserList = followers.OrderByDescending(x => x.Followings.Count).ToList(); - + ResetLists(); } @@ -26,7 +27,8 @@ namespace BSLManager.Domain foreach (var follower in _sourceUserList) { - var displayedUser = $"{GetFullHandle(follower)} ({follower.Followings.Count}) (err:{follower.PostingErrorCount})"; + var displayedUser = + $"{GetFullHandle(follower)} ({follower.Followings.Count}) (err:{follower.PostingErrorCount})"; _filteredDisplayableUserList.Add(displayedUser); } } @@ -50,8 +52,10 @@ namespace BSLManager.Domain foreach (var el in elToRemove) { _filteredSourceUserList.Remove(el); - - var dElToRemove = _filteredDisplayableUserList.First(x => x.Contains(GetFullHandle(el))); + + var dElToRemove = _filteredDisplayableUserList.First( + x => x.Contains(GetFullHandle(el)) + ); _filteredDisplayableUserList.Remove(dElToRemove); } } @@ -78,4 +82,4 @@ namespace BSLManager.Domain return _filteredSourceUserList[index]; } } -} \ No newline at end of file +} diff --git a/src/BSLManager/Program.cs b/src/BSLManager/Program.cs index 629ff25..4048732 100644 --- a/src/BSLManager/Program.cs +++ b/src/BSLManager/Program.cs @@ -1,19 +1,12 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; +using System; using System.Text; using System.Threading.Tasks; -using BirdsiteLive.Common.Settings; -using BirdsiteLive.DAL.Contracts; + using BSLManager.Tools; -using Microsoft.Extensions.Configuration; -using NStack; -using Terminal.Gui; namespace BSLManager { - class Program + internal class Program { static async Task Main(string[] args) { diff --git a/src/BSLManager/Tools/BasicLogger.cs b/src/BSLManager/Tools/BasicLogger.cs index dbb9265..c594af2 100644 --- a/src/BSLManager/Tools/BasicLogger.cs +++ b/src/BSLManager/Tools/BasicLogger.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.IO; namespace BSLManager.Tools @@ -7,7 +7,7 @@ namespace BSLManager.Tools { public static void Log(string log) { - File.AppendAllLines($"Log-{Guid.NewGuid()}.txt", new []{ log }); + File.AppendAllLines($"Log-{Guid.NewGuid()}.txt", new[] { log }); } } -} \ No newline at end of file +} diff --git a/src/BSLManager/Tools/ConsoleGui.cs b/src/BSLManager/Tools/ConsoleGui.cs index b6f7b6e..3fb136e 100644 --- a/src/BSLManager/Tools/ConsoleGui.cs +++ b/src/BSLManager/Tools/ConsoleGui.cs @@ -1,4 +1,5 @@ -using System.Reflection; +using System.Reflection; + using Terminal.Gui; namespace BSLManager.Tools @@ -12,4 +13,4 @@ namespace BSLManager.Tools .Invoke(null, null); } } -} \ No newline at end of file +} diff --git a/src/BSLManager/Tools/SettingsManager.cs b/src/BSLManager/Tools/SettingsManager.cs index 5ff6314..72537f7 100644 --- a/src/BSLManager/Tools/SettingsManager.cs +++ b/src/BSLManager/Tools/SettingsManager.cs @@ -1,8 +1,11 @@ -using System; +using System; using System.IO; using System.Runtime.CompilerServices; + using BirdsiteLive.Common.Settings; + using Newtonsoft.Json; + using Org.BouncyCastle.Asn1.IsisMtt.X509; namespace BSLManager.Tools @@ -14,10 +17,13 @@ namespace BSLManager.Tools public (DbSettings dbSettings, InstanceSettings instanceSettings) GetSettings() { var localSettingsData = GetLocalSettingsFile(); - if (localSettingsData != null) return Convert(localSettingsData); + if (localSettingsData != null) + return Convert(localSettingsData); Console.WriteLine("We need to set up the manager"); - Console.WriteLine("Please provide the following information as provided in the docker-compose file"); + Console.WriteLine( + "Please provide the following information as provided in the docker-compose file" + ); LocalSettingsData data; do @@ -39,12 +45,11 @@ namespace BSLManager.Tools Console.WriteLine("Is it valid? (yes, no)"); resp = Console.ReadLine()?.Trim().ToLowerInvariant(); - if (resp == "n" || resp == "no") data = null; - + if (resp == "n" || resp == "no") + data = null; } while (resp != "y" && resp != "yes" && resp != "n" && resp != "no"); - } while (data == null); - + SaveLocalSettings(data); return Convert(data); } @@ -71,7 +76,9 @@ namespace BSLManager.Tools return data; } - private (DbSettings dbSettings, InstanceSettings instanceSettings) Convert(LocalSettingsData data) + private (DbSettings dbSettings, InstanceSettings instanceSettings) Convert( + LocalSettingsData data + ) { var dbSettings = new DbSettings { @@ -81,10 +88,7 @@ namespace BSLManager.Tools User = data.DbUser, Password = data.DbPassword }; - var instancesSettings = new InstanceSettings - { - Domain = data.InstanceDomain - }; + var instancesSettings = new InstanceSettings { Domain = data.InstanceDomain }; return (dbSettings, instancesSettings); } @@ -92,7 +96,8 @@ namespace BSLManager.Tools { try { - if (!File.Exists(LocalFileName)) return null; + if (!File.Exists(LocalFileName)) + return null; var jsonContent = File.ReadAllText(LocalFileName); var content = JsonConvert.DeserializeObject(jsonContent); @@ -121,4 +126,4 @@ namespace BSLManager.Tools public string InstanceDomain { get; set; } } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive.ActivityPub/ApDeserializer.cs b/src/BirdsiteLive.ActivityPub/ApDeserializer.cs index 17dadbe..570965c 100644 --- a/src/BirdsiteLive.ActivityPub/ApDeserializer.cs +++ b/src/BirdsiteLive.ActivityPub/ApDeserializer.cs @@ -1,4 +1,5 @@ -using System; +using System; + using Newtonsoft.Json; namespace BirdsiteLive.ActivityPub @@ -16,7 +17,7 @@ namespace BirdsiteLive.ActivityPub return JsonConvert.DeserializeObject(json); case "Undo": var a = JsonConvert.DeserializeObject(json); - if(a.apObject.type == "Follow") + if (a.apObject.type == "Follow") return JsonConvert.DeserializeObject(json); break; case "Accept": @@ -59,4 +60,4 @@ namespace BirdsiteLive.ActivityPub public Activity apObject { get; set; } } } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive.ActivityPub/BirdsiteLive.ActivityPub.csproj b/src/BirdsiteLive.ActivityPub/BirdsiteLive.ActivityPub.csproj index a690b63..d283d39 100644 --- a/src/BirdsiteLive.ActivityPub/BirdsiteLive.ActivityPub.csproj +++ b/src/BirdsiteLive.ActivityPub/BirdsiteLive.ActivityPub.csproj @@ -1,7 +1,7 @@ - netstandard2.0 + net6.0 diff --git a/src/BirdsiteLive.ActivityPub/Converters/ContextArrayConverter.cs b/src/BirdsiteLive.ActivityPub/Converters/ContextArrayConverter.cs index 21e139f..0115c0e 100644 --- a/src/BirdsiteLive.ActivityPub/Converters/ContextArrayConverter.cs +++ b/src/BirdsiteLive.ActivityPub/Converters/ContextArrayConverter.cs @@ -1,18 +1,28 @@ -using System; +using System; using System.Collections.Generic; + using Newtonsoft.Json; namespace BirdsiteLive.ActivityPub.Converters { public class ContextArrayConverter : JsonConverter { - public override bool CanWrite { get { return false; } } + public override bool CanWrite + { + get { return false; } + } + public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { throw new NotImplementedException(); } - public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + public override object ReadJson( + JsonReader reader, + Type objectType, + object existingValue, + JsonSerializer serializer + ) { var result = new List(); @@ -36,4 +46,4 @@ namespace BirdsiteLive.ActivityPub.Converters throw new NotImplementedException(); } } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive.ActivityPub/Converters/UrlFactory.cs b/src/BirdsiteLive.ActivityPub/Converters/UrlFactory.cs index 8abe5e2..6a4bad0 100644 --- a/src/BirdsiteLive.ActivityPub/Converters/UrlFactory.cs +++ b/src/BirdsiteLive.ActivityPub/Converters/UrlFactory.cs @@ -1,4 +1,4 @@ -using System.Runtime.CompilerServices; +using System.Runtime.CompilerServices; namespace BirdsiteLive.ActivityPub.Converters { @@ -14,4 +14,4 @@ namespace BirdsiteLive.ActivityPub.Converters return $"https://{domain.ToLowerInvariant()}/users/{username.ToLowerInvariant()}/statuses/{noteId}"; } } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive.ActivityPub/Models/Activity.cs b/src/BirdsiteLive.ActivityPub/Models/Activity.cs index 98456b7..ff73a25 100644 --- a/src/BirdsiteLive.ActivityPub/Models/Activity.cs +++ b/src/BirdsiteLive.ActivityPub/Models/Activity.cs @@ -1,5 +1,6 @@ -using System.Collections.Generic; +using System.Collections.Generic; using System.Text.Json.Serialization; + using Newtonsoft.Json; namespace BirdsiteLive.ActivityPub @@ -7,7 +8,8 @@ namespace BirdsiteLive.ActivityPub public class Activity { [Newtonsoft.Json.JsonIgnore] - public static readonly object[] DefaultContext = new object[] { + public static readonly object[] DefaultContext = new object[] + { "https://www.w3.org/ns/activitystreams", "https://w3id.org/security/v1", new Dictionary @@ -18,7 +20,6 @@ namespace BirdsiteLive.ActivityPub { "value", "schema:value" }, { "sensitive", "as:sensitive" }, { "quoteUrl", "as:quoteUrl" }, - { "schema", "http://schema.org#" }, { "toot", "https://joinmastodon.org/ns#" } } @@ -33,4 +34,4 @@ namespace BirdsiteLive.ActivityPub //[JsonProperty("object")] //public string apObject { get; set; } } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive.ActivityPub/Models/ActivityAccept.cs b/src/BirdsiteLive.ActivityPub/Models/ActivityAccept.cs index 30b8746..55246c5 100644 --- a/src/BirdsiteLive.ActivityPub/Models/ActivityAccept.cs +++ b/src/BirdsiteLive.ActivityPub/Models/ActivityAccept.cs @@ -1,4 +1,4 @@ -using Newtonsoft.Json; +using Newtonsoft.Json; namespace BirdsiteLive.ActivityPub { @@ -7,4 +7,4 @@ namespace BirdsiteLive.ActivityPub [JsonProperty("object")] public object apObject { get; set; } } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive.ActivityPub/Models/ActivityAcceptFollow.cs b/src/BirdsiteLive.ActivityPub/Models/ActivityAcceptFollow.cs index f833a43..81cf077 100644 --- a/src/BirdsiteLive.ActivityPub/Models/ActivityAcceptFollow.cs +++ b/src/BirdsiteLive.ActivityPub/Models/ActivityAcceptFollow.cs @@ -1,4 +1,4 @@ -using Newtonsoft.Json; +using Newtonsoft.Json; namespace BirdsiteLive.ActivityPub { @@ -7,4 +7,4 @@ namespace BirdsiteLive.ActivityPub [JsonProperty("object")] public ActivityFollow apObject { get; set; } } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive.ActivityPub/Models/ActivityAcceptUndoFollow.cs b/src/BirdsiteLive.ActivityPub/Models/ActivityAcceptUndoFollow.cs index 9453f25..ceb8864 100644 --- a/src/BirdsiteLive.ActivityPub/Models/ActivityAcceptUndoFollow.cs +++ b/src/BirdsiteLive.ActivityPub/Models/ActivityAcceptUndoFollow.cs @@ -1,4 +1,4 @@ -using Newtonsoft.Json; +using Newtonsoft.Json; namespace BirdsiteLive.ActivityPub { @@ -7,4 +7,4 @@ namespace BirdsiteLive.ActivityPub [JsonProperty("object")] public ActivityUndoFollow apObject { get; set; } } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive.ActivityPub/Models/ActivityCreate.cs b/src/BirdsiteLive.ActivityPub/Models/ActivityCreate.cs index 8532682..c4c0f96 100644 --- a/src/BirdsiteLive.ActivityPub/Models/ActivityCreate.cs +++ b/src/BirdsiteLive.ActivityPub/Models/ActivityCreate.cs @@ -1,7 +1,4 @@ -namespace BirdsiteLive.ActivityPub +namespace BirdsiteLive.ActivityPub { - public class ActivityCreate - { - - } -} \ No newline at end of file + public class ActivityCreate { } +} diff --git a/src/BirdsiteLive.ActivityPub/Models/ActivityCreateNote.cs b/src/BirdsiteLive.ActivityPub/Models/ActivityCreateNote.cs index fe14ac7..61b65eb 100644 --- a/src/BirdsiteLive.ActivityPub/Models/ActivityCreateNote.cs +++ b/src/BirdsiteLive.ActivityPub/Models/ActivityCreateNote.cs @@ -1,5 +1,7 @@ -using System; +using System; + using BirdsiteLive.ActivityPub.Models; + using Newtonsoft.Json; namespace BirdsiteLive.ActivityPub @@ -13,4 +15,4 @@ namespace BirdsiteLive.ActivityPub [JsonProperty("object")] public Note apObject { get; set; } } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive.ActivityPub/Models/ActivityFollow.cs b/src/BirdsiteLive.ActivityPub/Models/ActivityFollow.cs index 26676f1..5b6333e 100644 --- a/src/BirdsiteLive.ActivityPub/Models/ActivityFollow.cs +++ b/src/BirdsiteLive.ActivityPub/Models/ActivityFollow.cs @@ -1,4 +1,4 @@ -using Newtonsoft.Json; +using Newtonsoft.Json; namespace BirdsiteLive.ActivityPub { @@ -7,4 +7,4 @@ namespace BirdsiteLive.ActivityPub [JsonProperty("object")] public string apObject { get; set; } } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive.ActivityPub/Models/ActivityRejectFollow.cs b/src/BirdsiteLive.ActivityPub/Models/ActivityRejectFollow.cs index da5d613..d80b859 100644 --- a/src/BirdsiteLive.ActivityPub/Models/ActivityRejectFollow.cs +++ b/src/BirdsiteLive.ActivityPub/Models/ActivityRejectFollow.cs @@ -1,4 +1,4 @@ -using Newtonsoft.Json; +using Newtonsoft.Json; namespace BirdsiteLive.ActivityPub { @@ -7,4 +7,4 @@ namespace BirdsiteLive.ActivityPub [JsonProperty("object")] public ActivityFollow apObject { get; set; } } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive.ActivityPub/Models/ActivityUndo.cs b/src/BirdsiteLive.ActivityPub/Models/ActivityUndo.cs index 2d98b5d..5384141 100644 --- a/src/BirdsiteLive.ActivityPub/Models/ActivityUndo.cs +++ b/src/BirdsiteLive.ActivityPub/Models/ActivityUndo.cs @@ -1,4 +1,4 @@ -using Newtonsoft.Json; +using Newtonsoft.Json; namespace BirdsiteLive.ActivityPub { @@ -7,4 +7,4 @@ namespace BirdsiteLive.ActivityPub [JsonProperty("object")] public Activity apObject { get; set; } } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive.ActivityPub/Models/ActivityUndoFollow.cs b/src/BirdsiteLive.ActivityPub/Models/ActivityUndoFollow.cs index 624988f..61943e2 100644 --- a/src/BirdsiteLive.ActivityPub/Models/ActivityUndoFollow.cs +++ b/src/BirdsiteLive.ActivityPub/Models/ActivityUndoFollow.cs @@ -1,4 +1,4 @@ -using Newtonsoft.Json; +using Newtonsoft.Json; namespace BirdsiteLive.ActivityPub { @@ -7,4 +7,4 @@ namespace BirdsiteLive.ActivityPub [JsonProperty("object")] public ActivityFollow apObject { get; set; } } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive.ActivityPub/Models/Actor.cs b/src/BirdsiteLive.ActivityPub/Models/Actor.cs index 12905be..c46c87e 100644 --- a/src/BirdsiteLive.ActivityPub/Models/Actor.cs +++ b/src/BirdsiteLive.ActivityPub/Models/Actor.cs @@ -1,8 +1,10 @@ -using System; +using System; using System.Collections.Generic; using System.Net; + using BirdsiteLive.ActivityPub.Converters; using BirdsiteLive.ActivityPub.Models; + using Newtonsoft.Json; namespace BirdsiteLive.ActivityPub diff --git a/src/BirdsiteLive.ActivityPub/Models/Attachment.cs b/src/BirdsiteLive.ActivityPub/Models/Attachment.cs index d7b86dd..646852b 100644 --- a/src/BirdsiteLive.ActivityPub/Models/Attachment.cs +++ b/src/BirdsiteLive.ActivityPub/Models/Attachment.cs @@ -1,4 +1,4 @@ -namespace BirdsiteLive.ActivityPub +namespace BirdsiteLive.ActivityPub { public class Attachment { @@ -6,4 +6,4 @@ public string mediaType { get; set; } public string url { get; set; } } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive.ActivityPub/Models/EndPoints.cs b/src/BirdsiteLive.ActivityPub/Models/EndPoints.cs index 8d671d5..21d147d 100644 --- a/src/BirdsiteLive.ActivityPub/Models/EndPoints.cs +++ b/src/BirdsiteLive.ActivityPub/Models/EndPoints.cs @@ -1,7 +1,7 @@ -namespace BirdsiteLive.ActivityPub +namespace BirdsiteLive.ActivityPub { public class EndPoints { public string sharedInbox { get; set; } } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive.ActivityPub/Models/Followers.cs b/src/BirdsiteLive.ActivityPub/Models/Followers.cs index 1a25ff6..a94afb9 100644 --- a/src/BirdsiteLive.ActivityPub/Models/Followers.cs +++ b/src/BirdsiteLive.ActivityPub/Models/Followers.cs @@ -1,4 +1,5 @@ -using BirdsiteLive.ActivityPub.Converters; +using BirdsiteLive.ActivityPub.Converters; + using Newtonsoft.Json; namespace BirdsiteLive.ActivityPub.Models @@ -12,4 +13,4 @@ namespace BirdsiteLive.ActivityPub.Models public string id { get; set; } public string type { get; set; } = "OrderedCollection"; } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive.ActivityPub/Models/Image.cs b/src/BirdsiteLive.ActivityPub/Models/Image.cs index 22c09fd..1ad768b 100644 --- a/src/BirdsiteLive.ActivityPub/Models/Image.cs +++ b/src/BirdsiteLive.ActivityPub/Models/Image.cs @@ -1,4 +1,4 @@ -namespace BirdsiteLive.ActivityPub +namespace BirdsiteLive.ActivityPub { public class Image { @@ -6,4 +6,4 @@ public string mediaType { get; set; } public string url { get; set; } } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive.ActivityPub/Models/Note.cs b/src/BirdsiteLive.ActivityPub/Models/Note.cs index 5083ab5..be99cfa 100644 --- a/src/BirdsiteLive.ActivityPub/Models/Note.cs +++ b/src/BirdsiteLive.ActivityPub/Models/Note.cs @@ -1,7 +1,9 @@ -using BirdsiteLive.ActivityPub.Converters; -using Newtonsoft.Json; using System.Collections.Generic; +using BirdsiteLive.ActivityPub.Converters; + +using Newtonsoft.Json; + namespace BirdsiteLive.ActivityPub.Models { public class Note @@ -20,13 +22,16 @@ namespace BirdsiteLive.ActivityPub.Models public string[] to { get; set; } public string[] cc { get; set; } public bool sensitive { get; set; } + //public string conversation { get; set; } public string content { get; set; } + //public Dictionary contentMap { get; set; } public Attachment[] attachment { get; set; } public Tag[] tag { get; set; } + //public Dictionary replies; public string quoteUrl { get; set; } } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive.ActivityPub/Models/PublicKey.cs b/src/BirdsiteLive.ActivityPub/Models/PublicKey.cs index 3c3b908..4743670 100644 --- a/src/BirdsiteLive.ActivityPub/Models/PublicKey.cs +++ b/src/BirdsiteLive.ActivityPub/Models/PublicKey.cs @@ -1,4 +1,4 @@ -namespace BirdsiteLive.ActivityPub +namespace BirdsiteLive.ActivityPub { public class PublicKey { @@ -6,4 +6,4 @@ public string owner { get; set; } public string publicKeyPem { get; set; } } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive.ActivityPub/Models/Tag.cs b/src/BirdsiteLive.ActivityPub/Models/Tag.cs index 34be51c..6ee8d30 100644 --- a/src/BirdsiteLive.ActivityPub/Models/Tag.cs +++ b/src/BirdsiteLive.ActivityPub/Models/Tag.cs @@ -1,8 +1,9 @@ -using System; +using System; namespace BirdsiteLive.ActivityPub.Models { - public class Tag { + public class Tag + { public TagResource icon { get; set; } = null; public string id { get; set; } public string type { get; set; } //Hashtag @@ -16,4 +17,4 @@ namespace BirdsiteLive.ActivityPub.Models public string type { get; set; } public string url { get; set; } } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive.ActivityPub/Models/UserAttachment.cs b/src/BirdsiteLive.ActivityPub/Models/UserAttachment.cs index 1b7df37..807402e 100644 --- a/src/BirdsiteLive.ActivityPub/Models/UserAttachment.cs +++ b/src/BirdsiteLive.ActivityPub/Models/UserAttachment.cs @@ -1,4 +1,4 @@ -namespace BirdsiteLive.ActivityPub +namespace BirdsiteLive.ActivityPub { public class UserAttachment { @@ -6,4 +6,4 @@ public string name { get; set; } public string value { get; set; } } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive.ActivityPub/Models/WebFingerData.cs b/src/BirdsiteLive.ActivityPub/Models/WebFingerData.cs index 31dc1b8..0c1fae0 100644 --- a/src/BirdsiteLive.ActivityPub/Models/WebFingerData.cs +++ b/src/BirdsiteLive.ActivityPub/Models/WebFingerData.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Text; diff --git a/src/BirdsiteLive.Common/BirdsiteLive.Common.csproj b/src/BirdsiteLive.Common/BirdsiteLive.Common.csproj index 9f5c4f4..dbc1517 100644 --- a/src/BirdsiteLive.Common/BirdsiteLive.Common.csproj +++ b/src/BirdsiteLive.Common/BirdsiteLive.Common.csproj @@ -1,7 +1,7 @@ - netstandard2.0 + net6.0 diff --git a/src/BirdsiteLive.Common/Extensions/EnumerableExt.cs b/src/BirdsiteLive.Common/Extensions/EnumerableExt.cs index 51b117b..3eedf78 100644 --- a/src/BirdsiteLive.Common/Extensions/EnumerableExt.cs +++ b/src/BirdsiteLive.Common/Extensions/EnumerableExt.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; namespace BirdsiteLive.Common.Extensions @@ -13,4 +13,4 @@ namespace BirdsiteLive.Common.Extensions } } } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive.Common/Regexes/EmojiRegexes.cs b/src/BirdsiteLive.Common/Regexes/EmojiRegexes.cs index a6b8ae5..ad8e931 100644 --- a/src/BirdsiteLive.Common/Regexes/EmojiRegexes.cs +++ b/src/BirdsiteLive.Common/Regexes/EmojiRegexes.cs @@ -1,11 +1,12 @@ -using System.Text.RegularExpressions; +using System.Text.RegularExpressions; namespace BirdsiteLive.Common.Regexes { public class EmojiRegexes { public static readonly Regex Emoji = new Regex(EmojiPattern); - - private const string EmojiPattern = @"(?:\uD83D(?:\uDD73\uFE0F?|\uDC41(?:(?:\uFE0F(?:\u200D\uD83D\uDDE8\uFE0F?)?|\u200D\uD83D\uDDE8\uFE0F?))?|[\uDDE8\uDDEF]\uFE0F?|\uDC4B(?:\uD83C[\uDFFB-\uDFFF])?|\uDD90(?:(?:\uD83C[\uDFFB-\uDFFF]|\uFE0F))?|[\uDD96\uDC4C\uDC48\uDC49\uDC46\uDD95\uDC47\uDC4D\uDC4E\uDC4A\uDC4F\uDE4C\uDC50\uDE4F\uDC85\uDCAA\uDC42\uDC43\uDC76\uDC66\uDC67](?:\uD83C[\uDFFB-\uDFFF])?|\uDC71(?:(?:\uD83C(?:[\uDFFB-\uDFFF](?:\u200D(?:[\u2640\u2642]\uFE0F?))?)|\u200D(?:[\u2640\u2642]\uFE0F?)))?|\uDC68(?:(?:\uD83C(?:\uDFFB(?:\u200D(?:\uD83E(?:\uDD1D\u200D\uD83D\uDC68\uD83C[\uDFFC-\uDFFF]|[\uDDB0\uDDB1\uDDB3\uDDB2\uDDAF\uDDBC\uDDBD])|\u2695\uFE0F?|\uD83C[\uDF93\uDFEB\uDF3E\uDF73\uDFED\uDFA4\uDFA8]|\u2696\uFE0F?|\uD83D[\uDD27\uDCBC\uDD2C\uDCBB\uDE80\uDE92]|\u2708\uFE0F?))?|\uDFFC(?:\u200D(?:\uD83E(?:\uDD1D\u200D\uD83D\uDC68\uD83C[\uDFFB\uDFFD-\uDFFF]|[\uDDB0\uDDB1\uDDB3\uDDB2\uDDAF\uDDBC\uDDBD])|\u2695\uFE0F?|\uD83C[\uDF93\uDFEB\uDF3E\uDF73\uDFED\uDFA4\uDFA8]|\u2696\uFE0F?|\uD83D[\uDD27\uDCBC\uDD2C\uDCBB\uDE80\uDE92]|\u2708\uFE0F?))?|\uDFFD(?:\u200D(?:\uD83E(?:\uDD1D\u200D\uD83D\uDC68\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF]|[\uDDB0\uDDB1\uDDB3\uDDB2\uDDAF\uDDBC\uDDBD])|\u2695\uFE0F?|\uD83C[\uDF93\uDFEB\uDF3E\uDF73\uDFED\uDFA4\uDFA8]|\u2696\uFE0F?|\uD83D[\uDD27\uDCBC\uDD2C\uDCBB\uDE80\uDE92]|\u2708\uFE0F?))?|\uDFFE(?:\u200D(?:\uD83E(?:\uDD1D\u200D\uD83D\uDC68\uD83C[\uDFFB-\uDFFD\uDFFF]|[\uDDB0\uDDB1\uDDB3\uDDB2\uDDAF\uDDBC\uDDBD])|\u2695\uFE0F?|\uD83C[\uDF93\uDFEB\uDF3E\uDF73\uDFED\uDFA4\uDFA8]|\u2696\uFE0F?|\uD83D[\uDD27\uDCBC\uDD2C\uDCBB\uDE80\uDE92]|\u2708\uFE0F?))?|\uDFFF(?:\u200D(?:\uD83E(?:\uDD1D\u200D\uD83D\uDC68\uD83C[\uDFFB-\uDFFE]|[\uDDB0\uDDB1\uDDB3\uDDB2\uDDAF\uDDBC\uDDBD])|\u2695\uFE0F?|\uD83C[\uDF93\uDFEB\uDF3E\uDF73\uDFED\uDFA4\uDFA8]|\u2696\uFE0F?|\uD83D[\uDD27\uDCBC\uDD2C\uDCBB\uDE80\uDE92]|\u2708\uFE0F?))?)|\u200D(?:\uD83E[\uDDB0\uDDB1\uDDB3\uDDB2\uDDAF\uDDBC\uDDBD]|\u2695\uFE0F?|\uD83C[\uDF93\uDFEB\uDF3E\uDF73\uDFED\uDFA4\uDFA8]|\u2696\uFE0F?|\uD83D(?:\uDC69\u200D\uD83D(?:\uDC66(?:\u200D\uD83D\uDC66)?|\uDC67(?:\u200D\uD83D[\uDC66\uDC67])?)|\uDC68\u200D\uD83D(?:\uDC66(?:\u200D\uD83D\uDC66)?|\uDC67(?:\u200D\uD83D[\uDC66\uDC67])?)|\uDC66(?:\u200D\uD83D\uDC66)?|\uDC67(?:\u200D\uD83D[\uDC66\uDC67])?|[\uDD27\uDCBC\uDD2C\uDCBB\uDE80\uDE92])|\u2708\uFE0F?|\u2764(?:\uFE0F\u200D\uD83D(?:\uDC8B\u200D\uD83D\uDC68|\uDC68)|\u200D\uD83D(?:\uDC8B\u200D\uD83D\uDC68|\uDC68)))))?|\uDC69(?:(?:\uD83C(?:\uDFFB(?:\u200D(?:\uD83E(?:\uDD1D\u200D\uD83D(?:\uDC69\uD83C[\uDFFC-\uDFFF]|\uDC68\uD83C[\uDFFC-\uDFFF])|[\uDDB0\uDDB1\uDDB3\uDDB2\uDDAF\uDDBC\uDDBD])|\u2695\uFE0F?|\uD83C[\uDF93\uDFEB\uDF3E\uDF73\uDFED\uDFA4\uDFA8]|\u2696\uFE0F?|\uD83D[\uDD27\uDCBC\uDD2C\uDCBB\uDE80\uDE92]|\u2708\uFE0F?))?|\uDFFC(?:\u200D(?:\uD83E(?:\uDD1D\u200D\uD83D(?:\uDC69\uD83C[\uDFFB\uDFFD-\uDFFF]|\uDC68\uD83C[\uDFFB\uDFFD-\uDFFF])|[\uDDB0\uDDB1\uDDB3\uDDB2\uDDAF\uDDBC\uDDBD])|\u2695\uFE0F?|\uD83C[\uDF93\uDFEB\uDF3E\uDF73\uDFED\uDFA4\uDFA8]|\u2696\uFE0F?|\uD83D[\uDD27\uDCBC\uDD2C\uDCBB\uDE80\uDE92]|\u2708\uFE0F?))?|\uDFFD(?:\u200D(?:\uD83E(?:\uDD1D\u200D\uD83D(?:\uDC69\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF]|\uDC68\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF])|[\uDDB0\uDDB1\uDDB3\uDDB2\uDDAF\uDDBC\uDDBD])|\u2695\uFE0F?|\uD83C[\uDF93\uDFEB\uDF3E\uDF73\uDFED\uDFA4\uDFA8]|\u2696\uFE0F?|\uD83D[\uDD27\uDCBC\uDD2C\uDCBB\uDE80\uDE92]|\u2708\uFE0F?))?|\uDFFE(?:\u200D(?:\uD83E(?:\uDD1D\u200D\uD83D(?:\uDC69\uD83C[\uDFFB-\uDFFD\uDFFF]|\uDC68\uD83C[\uDFFB-\uDFFD\uDFFF])|[\uDDB0\uDDB1\uDDB3\uDDB2\uDDAF\uDDBC\uDDBD])|\u2695\uFE0F?|\uD83C[\uDF93\uDFEB\uDF3E\uDF73\uDFED\uDFA4\uDFA8]|\u2696\uFE0F?|\uD83D[\uDD27\uDCBC\uDD2C\uDCBB\uDE80\uDE92]|\u2708\uFE0F?))?|\uDFFF(?:\u200D(?:\uD83E(?:\uDD1D\u200D\uD83D(?:\uDC69\uD83C[\uDFFB-\uDFFE]|\uDC68\uD83C[\uDFFB-\uDFFE])|[\uDDB0\uDDB1\uDDB3\uDDB2\uDDAF\uDDBC\uDDBD])|\u2695\uFE0F?|\uD83C[\uDF93\uDFEB\uDF3E\uDF73\uDFED\uDFA4\uDFA8]|\u2696\uFE0F?|\uD83D[\uDD27\uDCBC\uDD2C\uDCBB\uDE80\uDE92]|\u2708\uFE0F?))?)|\u200D(?:\uD83E[\uDDB0\uDDB1\uDDB3\uDDB2\uDDAF\uDDBC\uDDBD]|\u2695\uFE0F?|\uD83C[\uDF93\uDFEB\uDF3E\uDF73\uDFED\uDFA4\uDFA8]|\u2696\uFE0F?|\uD83D(?:\uDC69\u200D\uD83D(?:\uDC66(?:\u200D\uD83D\uDC66)?|\uDC67(?:\u200D\uD83D[\uDC66\uDC67])?)|\uDC66(?:\u200D\uD83D\uDC66)?|\uDC67(?:\u200D\uD83D[\uDC66\uDC67])?|[\uDD27\uDCBC\uDD2C\uDCBB\uDE80\uDE92])|\u2708\uFE0F?|\u2764(?:\uFE0F\u200D\uD83D(?:\uDC8B\u200D\uD83D[\uDC68\uDC69]|[\uDC68\uDC69])|\u200D\uD83D(?:\uDC8B\u200D\uD83D[\uDC68\uDC69]|[\uDC68\uDC69])))))?|[\uDC74\uDC75](?:\uD83C[\uDFFB-\uDFFF])?|[\uDE4D\uDE4E\uDE45\uDE46\uDC81\uDE4B\uDE47\uDC6E](?:(?:\uD83C(?:[\uDFFB-\uDFFF](?:\u200D(?:[\u2642\u2640]\uFE0F?))?)|\u200D(?:[\u2642\u2640]\uFE0F?)))?|\uDD75(?:(?:\uFE0F(?:\u200D(?:[\u2642\u2640]\uFE0F?))?|\uD83C(?:[\uDFFB-\uDFFF](?:\u200D(?:[\u2642\u2640]\uFE0F?))?)|\u200D(?:[\u2642\u2640]\uFE0F?)))?|[\uDC82\uDC77](?:(?:\uD83C(?:[\uDFFB-\uDFFF](?:\u200D(?:[\u2642\u2640]\uFE0F?))?)|\u200D(?:[\u2642\u2640]\uFE0F?)))?|\uDC78(?:\uD83C[\uDFFB-\uDFFF])?|\uDC73(?:(?:\uD83C(?:[\uDFFB-\uDFFF](?:\u200D(?:[\u2642\u2640]\uFE0F?))?)|\u200D(?:[\u2642\u2640]\uFE0F?)))?|[\uDC72\uDC70\uDC7C](?:\uD83C[\uDFFB-\uDFFF])?|[\uDC86\uDC87\uDEB6](?:(?:\uD83C(?:[\uDFFB-\uDFFF](?:\u200D(?:[\u2642\u2640]\uFE0F?))?)|\u200D(?:[\u2642\u2640]\uFE0F?)))?|[\uDC83\uDD7A](?:\uD83C[\uDFFB-\uDFFF])?|\uDD74(?:(?:\uD83C[\uDFFB-\uDFFF]|\uFE0F))?|\uDC6F(?:\u200D(?:[\u2642\u2640]\uFE0F?))?|[\uDEA3\uDEB4\uDEB5](?:(?:\uD83C(?:[\uDFFB-\uDFFF](?:\u200D(?:[\u2642\u2640]\uFE0F?))?)|\u200D(?:[\u2642\u2640]\uFE0F?)))?|[\uDEC0\uDECC\uDC6D\uDC6B\uDC6C](?:\uD83C[\uDFFB-\uDFFF])?|\uDDE3\uFE0F?|\uDC15(?:\u200D\uD83E\uDDBA)?|[\uDC3F\uDD4A\uDD77\uDD78\uDDFA\uDEE3\uDEE4\uDEE2\uDEF3\uDEE5\uDEE9\uDEF0\uDECE\uDD70\uDD79\uDDBC\uDD76\uDECD\uDDA5\uDDA8\uDDB1\uDDB2\uDCFD\uDD6F\uDDDE\uDDF3\uDD8B\uDD8A\uDD8C\uDD8D\uDDC2\uDDD2\uDDD3\uDD87\uDDC3\uDDC4\uDDD1\uDDDD\uDEE0\uDDE1\uDEE1\uDDDC\uDECF\uDECB\uDD49]\uFE0F?|[\uDE00\uDE03\uDE04\uDE01\uDE06\uDE05\uDE02\uDE42\uDE43\uDE09\uDE0A\uDE07\uDE0D\uDE18\uDE17\uDE1A\uDE19\uDE0B\uDE1B-\uDE1D\uDE10\uDE11\uDE36\uDE0F\uDE12\uDE44\uDE2C\uDE0C\uDE14\uDE2A\uDE34\uDE37\uDE35\uDE0E\uDE15\uDE1F\uDE41\uDE2E\uDE2F\uDE32\uDE33\uDE26-\uDE28\uDE30\uDE25\uDE22\uDE2D\uDE31\uDE16\uDE23\uDE1E\uDE13\uDE29\uDE2B\uDE24\uDE21\uDE20\uDE08\uDC7F\uDC80\uDCA9\uDC79-\uDC7B\uDC7D\uDC7E\uDE3A\uDE38\uDE39\uDE3B-\uDE3D\uDE40\uDE3F\uDE3E\uDE48-\uDE4A\uDC8B\uDC8C\uDC98\uDC9D\uDC96\uDC97\uDC93\uDC9E\uDC95\uDC9F\uDC94\uDC9B\uDC9A\uDC99\uDC9C\uDDA4\uDCAF\uDCA2\uDCA5\uDCAB\uDCA6\uDCA8\uDCA3\uDCAC\uDCAD\uDCA4\uDC40\uDC45\uDC44\uDC8F\uDC91\uDC6A\uDC64\uDC65\uDC63\uDC35\uDC12\uDC36\uDC29\uDC3A\uDC31\uDC08\uDC2F\uDC05\uDC06\uDC34\uDC0E\uDC2E\uDC02-\uDC04\uDC37\uDC16\uDC17\uDC3D\uDC0F\uDC11\uDC10\uDC2A\uDC2B\uDC18\uDC2D\uDC01\uDC00\uDC39\uDC30\uDC07\uDC3B\uDC28\uDC3C\uDC3E\uDC14\uDC13\uDC23-\uDC27\uDC38\uDC0A\uDC22\uDC0D\uDC32\uDC09\uDC33\uDC0B\uDC2C\uDC1F-\uDC21\uDC19\uDC1A\uDC0C\uDC1B-\uDC1E\uDC90\uDCAE\uDD2A\uDDFE\uDDFB\uDC92\uDDFC\uDDFD\uDD4C\uDED5\uDD4D\uDD4B\uDC88\uDE82-\uDE8A\uDE9D\uDE9E\uDE8B-\uDE8E\uDE90-\uDE9C\uDEF5\uDEFA\uDEB2\uDEF4\uDEF9\uDE8F\uDEA8\uDEA5\uDEA6\uDED1\uDEA7\uDEF6\uDEA4\uDEA2\uDEEB\uDEEC\uDCBA\uDE81\uDE9F-\uDEA1\uDE80\uDEF8\uDD5B\uDD67\uDD50\uDD5C\uDD51\uDD5D\uDD52\uDD5E\uDD53\uDD5F\uDD54\uDD60\uDD55\uDD61\uDD56\uDD62\uDD57\uDD63\uDD58\uDD64\uDD59\uDD65\uDD5A\uDD66\uDD25\uDCA7\uDEF7\uDD2E\uDC53-\uDC62\uDC51\uDC52\uDCFF\uDC84\uDC8D\uDC8E\uDD07-\uDD0A\uDCE2\uDCE3\uDCEF\uDD14\uDD15\uDCFB\uDCF1\uDCF2\uDCDE-\uDCE0\uDD0B\uDD0C\uDCBB\uDCBD-\uDCC0\uDCFA\uDCF7-\uDCF9\uDCFC\uDD0D\uDD0E\uDCA1\uDD26\uDCD4-\uDCDA\uDCD3\uDCD2\uDCC3\uDCDC\uDCC4\uDCF0\uDCD1\uDD16\uDCB0\uDCB4-\uDCB8\uDCB3\uDCB9\uDCB1\uDCB2\uDCE7-\uDCE9\uDCE4-\uDCE6\uDCEB\uDCEA\uDCEC-\uDCEE\uDCDD\uDCBC\uDCC1\uDCC2\uDCC5-\uDCD0\uDD12\uDD13\uDD0F-\uDD11\uDD28\uDD2B\uDD27\uDD29\uDD17\uDD2C\uDD2D\uDCE1\uDC89\uDC8A\uDEAA\uDEBD\uDEBF\uDEC1\uDED2\uDEAC\uDDFF\uDEAE\uDEB0\uDEB9-\uDEBC\uDEBE\uDEC2-\uDEC5\uDEB8\uDEAB\uDEB3\uDEAD\uDEAF\uDEB1\uDEB7\uDCF5\uDD1E\uDD03\uDD04\uDD19-\uDD1D\uDED0\uDD4E\uDD2F\uDD00-\uDD02\uDD3C\uDD3D\uDD05\uDD06\uDCF6\uDCF3\uDCF4\uDD31\uDCDB\uDD30\uDD1F-\uDD24\uDD34\uDFE0-\uDFE2\uDD35\uDFE3-\uDFE5\uDFE7-\uDFE9\uDFE6\uDFEA\uDFEB\uDD36-\uDD3B\uDCA0\uDD18\uDD33\uDD32\uDEA9])|\uD83E(?:[\uDD1A\uDD0F\uDD1E\uDD1F\uDD18\uDD19\uDD1B\uDD1C\uDD32\uDD33\uDDB5\uDDB6\uDDBB\uDDD2](?:\uD83C[\uDFFB-\uDFFF])?|\uDDD1(?:(?:\uD83C(?:[\uDFFB-\uDFFF](?:\u200D(?:\uD83E(?:\uDD1D\u200D\uD83E\uDDD1\uD83C[\uDFFB-\uDFFF]|[\uDDB0\uDDB1\uDDB3\uDDB2\uDDAF\uDDBC\uDDBD])|\u2695\uFE0F?|\uD83C[\uDF93\uDFEB\uDF3E\uDF73\uDFED\uDFA4\uDFA8]|\u2696\uFE0F?|\uD83D[\uDD27\uDCBC\uDD2C\uDCBB\uDE80\uDE92]|\u2708\uFE0F?))?)|\u200D(?:\uD83E(?:\uDD1D\u200D\uD83E\uDDD1|[\uDDB0\uDDB1\uDDB3\uDDB2\uDDAF\uDDBC\uDDBD])|\u2695\uFE0F?|\uD83C[\uDF93\uDFEB\uDF3E\uDF73\uDFED\uDFA4\uDFA8]|\u2696\uFE0F?|\uD83D[\uDD27\uDCBC\uDD2C\uDCBB\uDE80\uDE92]|\u2708\uFE0F?)))?|[\uDDD4\uDDD3](?:\uD83C[\uDFFB-\uDFFF])?|[\uDDCF\uDD26\uDD37](?:(?:\uD83C(?:[\uDFFB-\uDFFF](?:\u200D(?:[\u2642\u2640]\uFE0F?))?)|\u200D(?:[\u2642\u2640]\uFE0F?)))?|[\uDD34\uDDD5\uDD35\uDD30\uDD31\uDD36](?:\uD83C[\uDFFB-\uDFFF])?|[\uDDB8\uDDB9\uDDD9-\uDDDD](?:(?:\uD83C(?:[\uDFFB-\uDFFF](?:\u200D(?:[\u2642\u2640]\uFE0F?))?)|\u200D(?:[\u2642\u2640]\uFE0F?)))?|[\uDDDE\uDDDF](?:\u200D(?:[\u2642\u2640]\uFE0F?))?|[\uDDCD\uDDCE\uDDD6\uDDD7\uDD38](?:(?:\uD83C(?:[\uDFFB-\uDFFF](?:\u200D(?:[\u2642\u2640]\uFE0F?))?)|\u200D(?:[\u2642\u2640]\uFE0F?)))?|\uDD3C(?:\u200D(?:[\u2642\u2640]\uFE0F?))?|[\uDD3D\uDD3E\uDD39\uDDD8](?:(?:\uD83C(?:[\uDFFB-\uDFFF](?:\u200D(?:[\u2642\u2640]\uFE0F?))?)|\u200D(?:[\u2642\u2640]\uFE0F?)))?|[\uDD23\uDD70\uDD29\uDD2A\uDD11\uDD17\uDD2D\uDD2B\uDD14\uDD10\uDD28\uDD25\uDD24\uDD12\uDD15\uDD22\uDD2E\uDD27\uDD75\uDD76\uDD74\uDD2F\uDD20\uDD73\uDD13\uDDD0\uDD7A\uDD71\uDD2C\uDD21\uDD16\uDDE1\uDD0E\uDD0D\uDD1D\uDDBE\uDDBF\uDDE0\uDDB7\uDDB4\uDD3A\uDDB0\uDDB1\uDDB3\uDDB2\uDD8D\uDDA7\uDDAE\uDD8A\uDD9D\uDD81\uDD84\uDD93\uDD8C\uDD99\uDD92\uDD8F\uDD9B\uDD94\uDD87\uDDA5\uDDA6\uDDA8\uDD98\uDDA1\uDD83\uDD85\uDD86\uDDA2\uDD89\uDDA9\uDD9A\uDD9C\uDD8E\uDD95\uDD96\uDD88\uDD8B\uDD97\uDD82\uDD9F\uDDA0\uDD40\uDD6D\uDD5D\uDD65\uDD51\uDD54\uDD55\uDD52\uDD6C\uDD66\uDDC4\uDDC5\uDD5C\uDD50\uDD56\uDD68\uDD6F\uDD5E\uDDC7\uDDC0\uDD69\uDD53\uDD6A\uDD59\uDDC6\uDD5A\uDD58\uDD63\uDD57\uDDC8\uDDC2\uDD6B\uDD6E\uDD5F-\uDD61\uDD80\uDD9E\uDD90\uDD91\uDDAA\uDDC1\uDD67\uDD5B\uDD42\uDD43\uDD64\uDDC3\uDDC9\uDDCA\uDD62\uDD44\uDDED\uDDF1\uDDBD\uDDBC\uDE82\uDDF3\uDE90\uDDE8\uDDE7\uDD47-\uDD49\uDD4E\uDD4F\uDD4D\uDD4A\uDD4B\uDD45\uDD3F\uDD4C\uDE80\uDE81\uDDFF\uDDE9\uDDF8\uDDF5\uDDF6\uDD7D\uDD7C\uDDBA\uDDE3-\uDDE6\uDD7B\uDE71-\uDE73\uDD7E\uDD7F\uDE70\uDDE2\uDE95\uDD41\uDDEE\uDE94\uDDFE\uDE93\uDDAF\uDDF0\uDDF2\uDDEA-\uDDEC\uDE78-\uDE7A\uDE91\uDE92\uDDF4\uDDF7\uDDF9-\uDDFD\uDDEF])|[\u263A\u2639\u2620\u2763\u2764]\uFE0F?|\u270B(?:\uD83C[\uDFFB-\uDFFF])?|[\u270C\u261D](?:(?:\uD83C[\uDFFB-\uDFFF]|\uFE0F))?|\u270A(?:\uD83C[\uDFFB-\uDFFF])?|\u270D(?:(?:\uD83C[\uDFFB-\uDFFF]|\uFE0F))?|\uD83C(?:\uDF85(?:\uD83C[\uDFFB-\uDFFF])?|\uDFC3(?:(?:\uD83C(?:[\uDFFB-\uDFFF](?:\u200D(?:[\u2642\u2640]\uFE0F?))?)|\u200D(?:[\u2642\u2640]\uFE0F?)))?|[\uDFC7\uDFC2](?:\uD83C[\uDFFB-\uDFFF])?|\uDFCC(?:(?:\uFE0F(?:\u200D(?:[\u2642\u2640]\uFE0F?))?|\uD83C(?:[\uDFFB-\uDFFF](?:\u200D(?:[\u2642\u2640]\uFE0F?))?)|\u200D(?:[\u2642\u2640]\uFE0F?)))?|[\uDFC4\uDFCA](?:(?:\uD83C(?:[\uDFFB-\uDFFF](?:\u200D(?:[\u2642\u2640]\uFE0F?))?)|\u200D(?:[\u2642\u2640]\uFE0F?)))?|\uDFCB(?:(?:\uFE0F(?:\u200D(?:[\u2642\u2640]\uFE0F?))?|\uD83C(?:[\uDFFB-\uDFFF](?:\u200D(?:[\u2642\u2640]\uFE0F?))?)|\u200D(?:[\u2642\u2640]\uFE0F?)))?|[\uDFF5\uDF36\uDF7D\uDFD4-\uDFD6\uDFDC-\uDFDF\uDFDB\uDFD7\uDFD8\uDFDA\uDFD9\uDFCE\uDFCD\uDF21\uDF24-\uDF2C\uDF97\uDF9F\uDF96\uDF99-\uDF9B\uDF9E\uDFF7\uDD70\uDD71\uDD7E\uDD7F\uDE02\uDE37]\uFE0F?|\uDFF4(?:(?:\u200D\u2620\uFE0F?|\uDB40\uDC67\uDB40\uDC62\uDB40(?:\uDC65\uDB40\uDC6E\uDB40\uDC67\uDB40\uDC7F|\uDC73\uDB40\uDC63\uDB40\uDC74\uDB40\uDC7F|\uDC77\uDB40\uDC6C\uDB40\uDC73\uDB40\uDC7F)))?|\uDFF3(?:(?:\uFE0F(?:\u200D\uD83C\uDF08)?|\u200D\uD83C\uDF08))?|\uDDE6\uD83C[\uDDE8-\uDDEC\uDDEE\uDDF1\uDDF2\uDDF4\uDDF6-\uDDFA\uDDFC\uDDFD\uDDFF]|\uDDE7\uD83C[\uDDE6\uDDE7\uDDE9-\uDDEF\uDDF1-\uDDF4\uDDF6-\uDDF9\uDDFB\uDDFC\uDDFE\uDDFF]|\uDDE8\uD83C[\uDDE6\uDDE8\uDDE9\uDDEB-\uDDEE\uDDF0-\uDDF5\uDDF7\uDDFA-\uDDFF]|\uDDE9\uD83C[\uDDEA\uDDEC\uDDEF\uDDF0\uDDF2\uDDF4\uDDFF]|\uDDEA\uD83C[\uDDE6\uDDE8\uDDEA\uDDEC\uDDED\uDDF7-\uDDFA]|\uDDEB\uD83C[\uDDEE-\uDDF0\uDDF2\uDDF4\uDDF7]|\uDDEC\uD83C[\uDDE6\uDDE7\uDDE9-\uDDEE\uDDF1-\uDDF3\uDDF5-\uDDFA\uDDFC\uDDFE]|\uDDED\uD83C[\uDDF0\uDDF2\uDDF3\uDDF7\uDDF9\uDDFA]|\uDDEE\uD83C[\uDDE8-\uDDEA\uDDF1-\uDDF4\uDDF6-\uDDF9]|\uDDEF\uD83C[\uDDEA\uDDF2\uDDF4\uDDF5]|\uDDF0\uD83C[\uDDEA\uDDEC-\uDDEE\uDDF2\uDDF3\uDDF5\uDDF7\uDDFC\uDDFE\uDDFF]|\uDDF1\uD83C[\uDDE6-\uDDE8\uDDEE\uDDF0\uDDF7-\uDDFB\uDDFE]|\uDDF2\uD83C[\uDDE6\uDDE8-\uDDED\uDDF0-\uDDFF]|\uDDF3\uD83C[\uDDE6\uDDE8\uDDEA-\uDDEC\uDDEE\uDDF1\uDDF4\uDDF5\uDDF7\uDDFA\uDDFF]|\uDDF4\uD83C\uDDF2|\uDDF5\uD83C[\uDDE6\uDDEA-\uDDED\uDDF0-\uDDF3\uDDF7-\uDDF9\uDDFC\uDDFE]|\uDDF6\uD83C\uDDE6|\uDDF7\uD83C[\uDDEA\uDDF4\uDDF8\uDDFA\uDDFC]|\uDDF8\uD83C[\uDDE6-\uDDEA\uDDEC-\uDDF4\uDDF7-\uDDF9\uDDFB\uDDFD-\uDDFF]|\uDDF9\uD83C[\uDDE6\uDDE8\uDDE9\uDDEB-\uDDED\uDDEF-\uDDF4\uDDF7\uDDF9\uDDFB\uDDFC\uDDFF]|\uDDFA\uD83C[\uDDE6\uDDEC\uDDF2\uDDF3\uDDF8\uDDFE\uDDFF]|\uDDFB\uD83C[\uDDE6\uDDE8\uDDEA\uDDEC\uDDEE\uDDF3\uDDFA]|\uDDFC\uD83C[\uDDEB\uDDF8]|\uDDFD\uD83C\uDDF0|\uDDFE\uD83C[\uDDEA\uDDF9]|\uDDFF\uD83C[\uDDE6\uDDF2\uDDFC]|[\uDFFB-\uDFFF\uDF38-\uDF3C\uDF37\uDF31-\uDF35\uDF3E-\uDF43\uDF47-\uDF53\uDF45\uDF46\uDF3D\uDF44\uDF30\uDF5E\uDF56\uDF57\uDF54\uDF5F\uDF55\uDF2D-\uDF2F\uDF73\uDF72\uDF7F\uDF71\uDF58-\uDF5D\uDF60\uDF62-\uDF65\uDF61\uDF66-\uDF6A\uDF82\uDF70\uDF6B-\uDF6F\uDF7C\uDF75\uDF76\uDF7E\uDF77-\uDF7B\uDF74\uDFFA\uDF0D-\uDF10\uDF0B\uDFE0-\uDFE6\uDFE8-\uDFED\uDFEF\uDFF0\uDF01\uDF03-\uDF07\uDF09\uDFA0-\uDFA2\uDFAA\uDF11-\uDF20\uDF0C\uDF00\uDF08\uDF02\uDF0A\uDF83\uDF84\uDF86-\uDF8B\uDF8D-\uDF91\uDF80\uDF81\uDFAB\uDFC6\uDFC5\uDFC0\uDFD0\uDFC8\uDFC9\uDFBE\uDFB3\uDFCF\uDFD1-\uDFD3\uDFF8\uDFA3\uDFBD\uDFBF\uDFAF\uDFB1\uDFAE\uDFB0\uDFB2\uDCCF\uDC04\uDFB4\uDFAD\uDFA8\uDF92\uDFA9\uDF93\uDFBC\uDFB5\uDFB6\uDFA4\uDFA7\uDFB7-\uDFBB\uDFA5\uDFAC\uDFEE\uDFF9\uDFE7\uDFA6\uDD8E\uDD91-\uDD9A\uDE01\uDE36\uDE2F\uDE50\uDE39\uDE1A\uDE32\uDE51\uDE38\uDE34\uDE33\uDE3A\uDE35\uDFC1\uDF8C])|\u26F7\uFE0F?|\u26F9(?:(?:\uFE0F(?:\u200D(?:[\u2642\u2640]\uFE0F?))?|\uD83C(?:[\uDFFB-\uDFFF](?:\u200D(?:[\u2642\u2640]\uFE0F?))?)|\u200D(?:[\u2642\u2640]\uFE0F?)))?|[\u2618\u26F0\u26E9\u2668\u26F4\u2708\u23F1\u23F2\u2600\u2601\u26C8\u2602\u26F1\u2744\u2603\u2604\u26F8\u2660\u2665\u2666\u2663\u265F\u26D1\u260E\u2328\u2709\u270F\u2712\u2702\u26CF\u2692\u2694\u2699\u2696\u26D3\u2697\u26B0\u26B1\u26A0\u2622\u2623\u2B06\u2197\u27A1\u2198\u2B07\u2199\u2B05\u2196\u2195\u2194\u21A9\u21AA\u2934\u2935\u269B\u2721\u2638\u262F\u271D\u2626\u262A\u262E\u25B6\u23ED\u23EF\u25C0\u23EE\u23F8-\u23FA\u23CF\u2640\u2642\u2695\u267E\u267B\u269C\u2611\u2714\u2716\u303D\u2733\u2734\u2747\u203C\u2049\u3030\u00A9\u00AE\u2122]\uFE0F?|[\u0023\u002A\u0030-\u0039](?:\uFE0F\u20E3|\u20E3)|[\u2139\u24C2\u3297\u3299\u25FC\u25FB\u25AA\u25AB]\uFE0F?|[\u2615\u26EA\u26F2\u26FA\u26FD\u2693\u26F5\u231B\u23F3\u231A\u23F0\u2B50\u26C5\u2614\u26A1\u26C4\u2728\u26BD\u26BE\u26F3\u267F\u26D4\u2648-\u2653\u26CE\u23E9-\u23EC\u2B55\u2705\u274C\u274E\u2795-\u2797\u27B0\u27BF\u2753-\u2755\u2757\u26AB\u26AA\u2B1B\u2B1C\u25FE\u25FD])"; + + private const string EmojiPattern = + @"(?:\uD83D(?:\uDD73\uFE0F?|\uDC41(?:(?:\uFE0F(?:\u200D\uD83D\uDDE8\uFE0F?)?|\u200D\uD83D\uDDE8\uFE0F?))?|[\uDDE8\uDDEF]\uFE0F?|\uDC4B(?:\uD83C[\uDFFB-\uDFFF])?|\uDD90(?:(?:\uD83C[\uDFFB-\uDFFF]|\uFE0F))?|[\uDD96\uDC4C\uDC48\uDC49\uDC46\uDD95\uDC47\uDC4D\uDC4E\uDC4A\uDC4F\uDE4C\uDC50\uDE4F\uDC85\uDCAA\uDC42\uDC43\uDC76\uDC66\uDC67](?:\uD83C[\uDFFB-\uDFFF])?|\uDC71(?:(?:\uD83C(?:[\uDFFB-\uDFFF](?:\u200D(?:[\u2640\u2642]\uFE0F?))?)|\u200D(?:[\u2640\u2642]\uFE0F?)))?|\uDC68(?:(?:\uD83C(?:\uDFFB(?:\u200D(?:\uD83E(?:\uDD1D\u200D\uD83D\uDC68\uD83C[\uDFFC-\uDFFF]|[\uDDB0\uDDB1\uDDB3\uDDB2\uDDAF\uDDBC\uDDBD])|\u2695\uFE0F?|\uD83C[\uDF93\uDFEB\uDF3E\uDF73\uDFED\uDFA4\uDFA8]|\u2696\uFE0F?|\uD83D[\uDD27\uDCBC\uDD2C\uDCBB\uDE80\uDE92]|\u2708\uFE0F?))?|\uDFFC(?:\u200D(?:\uD83E(?:\uDD1D\u200D\uD83D\uDC68\uD83C[\uDFFB\uDFFD-\uDFFF]|[\uDDB0\uDDB1\uDDB3\uDDB2\uDDAF\uDDBC\uDDBD])|\u2695\uFE0F?|\uD83C[\uDF93\uDFEB\uDF3E\uDF73\uDFED\uDFA4\uDFA8]|\u2696\uFE0F?|\uD83D[\uDD27\uDCBC\uDD2C\uDCBB\uDE80\uDE92]|\u2708\uFE0F?))?|\uDFFD(?:\u200D(?:\uD83E(?:\uDD1D\u200D\uD83D\uDC68\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF]|[\uDDB0\uDDB1\uDDB3\uDDB2\uDDAF\uDDBC\uDDBD])|\u2695\uFE0F?|\uD83C[\uDF93\uDFEB\uDF3E\uDF73\uDFED\uDFA4\uDFA8]|\u2696\uFE0F?|\uD83D[\uDD27\uDCBC\uDD2C\uDCBB\uDE80\uDE92]|\u2708\uFE0F?))?|\uDFFE(?:\u200D(?:\uD83E(?:\uDD1D\u200D\uD83D\uDC68\uD83C[\uDFFB-\uDFFD\uDFFF]|[\uDDB0\uDDB1\uDDB3\uDDB2\uDDAF\uDDBC\uDDBD])|\u2695\uFE0F?|\uD83C[\uDF93\uDFEB\uDF3E\uDF73\uDFED\uDFA4\uDFA8]|\u2696\uFE0F?|\uD83D[\uDD27\uDCBC\uDD2C\uDCBB\uDE80\uDE92]|\u2708\uFE0F?))?|\uDFFF(?:\u200D(?:\uD83E(?:\uDD1D\u200D\uD83D\uDC68\uD83C[\uDFFB-\uDFFE]|[\uDDB0\uDDB1\uDDB3\uDDB2\uDDAF\uDDBC\uDDBD])|\u2695\uFE0F?|\uD83C[\uDF93\uDFEB\uDF3E\uDF73\uDFED\uDFA4\uDFA8]|\u2696\uFE0F?|\uD83D[\uDD27\uDCBC\uDD2C\uDCBB\uDE80\uDE92]|\u2708\uFE0F?))?)|\u200D(?:\uD83E[\uDDB0\uDDB1\uDDB3\uDDB2\uDDAF\uDDBC\uDDBD]|\u2695\uFE0F?|\uD83C[\uDF93\uDFEB\uDF3E\uDF73\uDFED\uDFA4\uDFA8]|\u2696\uFE0F?|\uD83D(?:\uDC69\u200D\uD83D(?:\uDC66(?:\u200D\uD83D\uDC66)?|\uDC67(?:\u200D\uD83D[\uDC66\uDC67])?)|\uDC68\u200D\uD83D(?:\uDC66(?:\u200D\uD83D\uDC66)?|\uDC67(?:\u200D\uD83D[\uDC66\uDC67])?)|\uDC66(?:\u200D\uD83D\uDC66)?|\uDC67(?:\u200D\uD83D[\uDC66\uDC67])?|[\uDD27\uDCBC\uDD2C\uDCBB\uDE80\uDE92])|\u2708\uFE0F?|\u2764(?:\uFE0F\u200D\uD83D(?:\uDC8B\u200D\uD83D\uDC68|\uDC68)|\u200D\uD83D(?:\uDC8B\u200D\uD83D\uDC68|\uDC68)))))?|\uDC69(?:(?:\uD83C(?:\uDFFB(?:\u200D(?:\uD83E(?:\uDD1D\u200D\uD83D(?:\uDC69\uD83C[\uDFFC-\uDFFF]|\uDC68\uD83C[\uDFFC-\uDFFF])|[\uDDB0\uDDB1\uDDB3\uDDB2\uDDAF\uDDBC\uDDBD])|\u2695\uFE0F?|\uD83C[\uDF93\uDFEB\uDF3E\uDF73\uDFED\uDFA4\uDFA8]|\u2696\uFE0F?|\uD83D[\uDD27\uDCBC\uDD2C\uDCBB\uDE80\uDE92]|\u2708\uFE0F?))?|\uDFFC(?:\u200D(?:\uD83E(?:\uDD1D\u200D\uD83D(?:\uDC69\uD83C[\uDFFB\uDFFD-\uDFFF]|\uDC68\uD83C[\uDFFB\uDFFD-\uDFFF])|[\uDDB0\uDDB1\uDDB3\uDDB2\uDDAF\uDDBC\uDDBD])|\u2695\uFE0F?|\uD83C[\uDF93\uDFEB\uDF3E\uDF73\uDFED\uDFA4\uDFA8]|\u2696\uFE0F?|\uD83D[\uDD27\uDCBC\uDD2C\uDCBB\uDE80\uDE92]|\u2708\uFE0F?))?|\uDFFD(?:\u200D(?:\uD83E(?:\uDD1D\u200D\uD83D(?:\uDC69\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF]|\uDC68\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF])|[\uDDB0\uDDB1\uDDB3\uDDB2\uDDAF\uDDBC\uDDBD])|\u2695\uFE0F?|\uD83C[\uDF93\uDFEB\uDF3E\uDF73\uDFED\uDFA4\uDFA8]|\u2696\uFE0F?|\uD83D[\uDD27\uDCBC\uDD2C\uDCBB\uDE80\uDE92]|\u2708\uFE0F?))?|\uDFFE(?:\u200D(?:\uD83E(?:\uDD1D\u200D\uD83D(?:\uDC69\uD83C[\uDFFB-\uDFFD\uDFFF]|\uDC68\uD83C[\uDFFB-\uDFFD\uDFFF])|[\uDDB0\uDDB1\uDDB3\uDDB2\uDDAF\uDDBC\uDDBD])|\u2695\uFE0F?|\uD83C[\uDF93\uDFEB\uDF3E\uDF73\uDFED\uDFA4\uDFA8]|\u2696\uFE0F?|\uD83D[\uDD27\uDCBC\uDD2C\uDCBB\uDE80\uDE92]|\u2708\uFE0F?))?|\uDFFF(?:\u200D(?:\uD83E(?:\uDD1D\u200D\uD83D(?:\uDC69\uD83C[\uDFFB-\uDFFE]|\uDC68\uD83C[\uDFFB-\uDFFE])|[\uDDB0\uDDB1\uDDB3\uDDB2\uDDAF\uDDBC\uDDBD])|\u2695\uFE0F?|\uD83C[\uDF93\uDFEB\uDF3E\uDF73\uDFED\uDFA4\uDFA8]|\u2696\uFE0F?|\uD83D[\uDD27\uDCBC\uDD2C\uDCBB\uDE80\uDE92]|\u2708\uFE0F?))?)|\u200D(?:\uD83E[\uDDB0\uDDB1\uDDB3\uDDB2\uDDAF\uDDBC\uDDBD]|\u2695\uFE0F?|\uD83C[\uDF93\uDFEB\uDF3E\uDF73\uDFED\uDFA4\uDFA8]|\u2696\uFE0F?|\uD83D(?:\uDC69\u200D\uD83D(?:\uDC66(?:\u200D\uD83D\uDC66)?|\uDC67(?:\u200D\uD83D[\uDC66\uDC67])?)|\uDC66(?:\u200D\uD83D\uDC66)?|\uDC67(?:\u200D\uD83D[\uDC66\uDC67])?|[\uDD27\uDCBC\uDD2C\uDCBB\uDE80\uDE92])|\u2708\uFE0F?|\u2764(?:\uFE0F\u200D\uD83D(?:\uDC8B\u200D\uD83D[\uDC68\uDC69]|[\uDC68\uDC69])|\u200D\uD83D(?:\uDC8B\u200D\uD83D[\uDC68\uDC69]|[\uDC68\uDC69])))))?|[\uDC74\uDC75](?:\uD83C[\uDFFB-\uDFFF])?|[\uDE4D\uDE4E\uDE45\uDE46\uDC81\uDE4B\uDE47\uDC6E](?:(?:\uD83C(?:[\uDFFB-\uDFFF](?:\u200D(?:[\u2642\u2640]\uFE0F?))?)|\u200D(?:[\u2642\u2640]\uFE0F?)))?|\uDD75(?:(?:\uFE0F(?:\u200D(?:[\u2642\u2640]\uFE0F?))?|\uD83C(?:[\uDFFB-\uDFFF](?:\u200D(?:[\u2642\u2640]\uFE0F?))?)|\u200D(?:[\u2642\u2640]\uFE0F?)))?|[\uDC82\uDC77](?:(?:\uD83C(?:[\uDFFB-\uDFFF](?:\u200D(?:[\u2642\u2640]\uFE0F?))?)|\u200D(?:[\u2642\u2640]\uFE0F?)))?|\uDC78(?:\uD83C[\uDFFB-\uDFFF])?|\uDC73(?:(?:\uD83C(?:[\uDFFB-\uDFFF](?:\u200D(?:[\u2642\u2640]\uFE0F?))?)|\u200D(?:[\u2642\u2640]\uFE0F?)))?|[\uDC72\uDC70\uDC7C](?:\uD83C[\uDFFB-\uDFFF])?|[\uDC86\uDC87\uDEB6](?:(?:\uD83C(?:[\uDFFB-\uDFFF](?:\u200D(?:[\u2642\u2640]\uFE0F?))?)|\u200D(?:[\u2642\u2640]\uFE0F?)))?|[\uDC83\uDD7A](?:\uD83C[\uDFFB-\uDFFF])?|\uDD74(?:(?:\uD83C[\uDFFB-\uDFFF]|\uFE0F))?|\uDC6F(?:\u200D(?:[\u2642\u2640]\uFE0F?))?|[\uDEA3\uDEB4\uDEB5](?:(?:\uD83C(?:[\uDFFB-\uDFFF](?:\u200D(?:[\u2642\u2640]\uFE0F?))?)|\u200D(?:[\u2642\u2640]\uFE0F?)))?|[\uDEC0\uDECC\uDC6D\uDC6B\uDC6C](?:\uD83C[\uDFFB-\uDFFF])?|\uDDE3\uFE0F?|\uDC15(?:\u200D\uD83E\uDDBA)?|[\uDC3F\uDD4A\uDD77\uDD78\uDDFA\uDEE3\uDEE4\uDEE2\uDEF3\uDEE5\uDEE9\uDEF0\uDECE\uDD70\uDD79\uDDBC\uDD76\uDECD\uDDA5\uDDA8\uDDB1\uDDB2\uDCFD\uDD6F\uDDDE\uDDF3\uDD8B\uDD8A\uDD8C\uDD8D\uDDC2\uDDD2\uDDD3\uDD87\uDDC3\uDDC4\uDDD1\uDDDD\uDEE0\uDDE1\uDEE1\uDDDC\uDECF\uDECB\uDD49]\uFE0F?|[\uDE00\uDE03\uDE04\uDE01\uDE06\uDE05\uDE02\uDE42\uDE43\uDE09\uDE0A\uDE07\uDE0D\uDE18\uDE17\uDE1A\uDE19\uDE0B\uDE1B-\uDE1D\uDE10\uDE11\uDE36\uDE0F\uDE12\uDE44\uDE2C\uDE0C\uDE14\uDE2A\uDE34\uDE37\uDE35\uDE0E\uDE15\uDE1F\uDE41\uDE2E\uDE2F\uDE32\uDE33\uDE26-\uDE28\uDE30\uDE25\uDE22\uDE2D\uDE31\uDE16\uDE23\uDE1E\uDE13\uDE29\uDE2B\uDE24\uDE21\uDE20\uDE08\uDC7F\uDC80\uDCA9\uDC79-\uDC7B\uDC7D\uDC7E\uDE3A\uDE38\uDE39\uDE3B-\uDE3D\uDE40\uDE3F\uDE3E\uDE48-\uDE4A\uDC8B\uDC8C\uDC98\uDC9D\uDC96\uDC97\uDC93\uDC9E\uDC95\uDC9F\uDC94\uDC9B\uDC9A\uDC99\uDC9C\uDDA4\uDCAF\uDCA2\uDCA5\uDCAB\uDCA6\uDCA8\uDCA3\uDCAC\uDCAD\uDCA4\uDC40\uDC45\uDC44\uDC8F\uDC91\uDC6A\uDC64\uDC65\uDC63\uDC35\uDC12\uDC36\uDC29\uDC3A\uDC31\uDC08\uDC2F\uDC05\uDC06\uDC34\uDC0E\uDC2E\uDC02-\uDC04\uDC37\uDC16\uDC17\uDC3D\uDC0F\uDC11\uDC10\uDC2A\uDC2B\uDC18\uDC2D\uDC01\uDC00\uDC39\uDC30\uDC07\uDC3B\uDC28\uDC3C\uDC3E\uDC14\uDC13\uDC23-\uDC27\uDC38\uDC0A\uDC22\uDC0D\uDC32\uDC09\uDC33\uDC0B\uDC2C\uDC1F-\uDC21\uDC19\uDC1A\uDC0C\uDC1B-\uDC1E\uDC90\uDCAE\uDD2A\uDDFE\uDDFB\uDC92\uDDFC\uDDFD\uDD4C\uDED5\uDD4D\uDD4B\uDC88\uDE82-\uDE8A\uDE9D\uDE9E\uDE8B-\uDE8E\uDE90-\uDE9C\uDEF5\uDEFA\uDEB2\uDEF4\uDEF9\uDE8F\uDEA8\uDEA5\uDEA6\uDED1\uDEA7\uDEF6\uDEA4\uDEA2\uDEEB\uDEEC\uDCBA\uDE81\uDE9F-\uDEA1\uDE80\uDEF8\uDD5B\uDD67\uDD50\uDD5C\uDD51\uDD5D\uDD52\uDD5E\uDD53\uDD5F\uDD54\uDD60\uDD55\uDD61\uDD56\uDD62\uDD57\uDD63\uDD58\uDD64\uDD59\uDD65\uDD5A\uDD66\uDD25\uDCA7\uDEF7\uDD2E\uDC53-\uDC62\uDC51\uDC52\uDCFF\uDC84\uDC8D\uDC8E\uDD07-\uDD0A\uDCE2\uDCE3\uDCEF\uDD14\uDD15\uDCFB\uDCF1\uDCF2\uDCDE-\uDCE0\uDD0B\uDD0C\uDCBB\uDCBD-\uDCC0\uDCFA\uDCF7-\uDCF9\uDCFC\uDD0D\uDD0E\uDCA1\uDD26\uDCD4-\uDCDA\uDCD3\uDCD2\uDCC3\uDCDC\uDCC4\uDCF0\uDCD1\uDD16\uDCB0\uDCB4-\uDCB8\uDCB3\uDCB9\uDCB1\uDCB2\uDCE7-\uDCE9\uDCE4-\uDCE6\uDCEB\uDCEA\uDCEC-\uDCEE\uDCDD\uDCBC\uDCC1\uDCC2\uDCC5-\uDCD0\uDD12\uDD13\uDD0F-\uDD11\uDD28\uDD2B\uDD27\uDD29\uDD17\uDD2C\uDD2D\uDCE1\uDC89\uDC8A\uDEAA\uDEBD\uDEBF\uDEC1\uDED2\uDEAC\uDDFF\uDEAE\uDEB0\uDEB9-\uDEBC\uDEBE\uDEC2-\uDEC5\uDEB8\uDEAB\uDEB3\uDEAD\uDEAF\uDEB1\uDEB7\uDCF5\uDD1E\uDD03\uDD04\uDD19-\uDD1D\uDED0\uDD4E\uDD2F\uDD00-\uDD02\uDD3C\uDD3D\uDD05\uDD06\uDCF6\uDCF3\uDCF4\uDD31\uDCDB\uDD30\uDD1F-\uDD24\uDD34\uDFE0-\uDFE2\uDD35\uDFE3-\uDFE5\uDFE7-\uDFE9\uDFE6\uDFEA\uDFEB\uDD36-\uDD3B\uDCA0\uDD18\uDD33\uDD32\uDEA9])|\uD83E(?:[\uDD1A\uDD0F\uDD1E\uDD1F\uDD18\uDD19\uDD1B\uDD1C\uDD32\uDD33\uDDB5\uDDB6\uDDBB\uDDD2](?:\uD83C[\uDFFB-\uDFFF])?|\uDDD1(?:(?:\uD83C(?:[\uDFFB-\uDFFF](?:\u200D(?:\uD83E(?:\uDD1D\u200D\uD83E\uDDD1\uD83C[\uDFFB-\uDFFF]|[\uDDB0\uDDB1\uDDB3\uDDB2\uDDAF\uDDBC\uDDBD])|\u2695\uFE0F?|\uD83C[\uDF93\uDFEB\uDF3E\uDF73\uDFED\uDFA4\uDFA8]|\u2696\uFE0F?|\uD83D[\uDD27\uDCBC\uDD2C\uDCBB\uDE80\uDE92]|\u2708\uFE0F?))?)|\u200D(?:\uD83E(?:\uDD1D\u200D\uD83E\uDDD1|[\uDDB0\uDDB1\uDDB3\uDDB2\uDDAF\uDDBC\uDDBD])|\u2695\uFE0F?|\uD83C[\uDF93\uDFEB\uDF3E\uDF73\uDFED\uDFA4\uDFA8]|\u2696\uFE0F?|\uD83D[\uDD27\uDCBC\uDD2C\uDCBB\uDE80\uDE92]|\u2708\uFE0F?)))?|[\uDDD4\uDDD3](?:\uD83C[\uDFFB-\uDFFF])?|[\uDDCF\uDD26\uDD37](?:(?:\uD83C(?:[\uDFFB-\uDFFF](?:\u200D(?:[\u2642\u2640]\uFE0F?))?)|\u200D(?:[\u2642\u2640]\uFE0F?)))?|[\uDD34\uDDD5\uDD35\uDD30\uDD31\uDD36](?:\uD83C[\uDFFB-\uDFFF])?|[\uDDB8\uDDB9\uDDD9-\uDDDD](?:(?:\uD83C(?:[\uDFFB-\uDFFF](?:\u200D(?:[\u2642\u2640]\uFE0F?))?)|\u200D(?:[\u2642\u2640]\uFE0F?)))?|[\uDDDE\uDDDF](?:\u200D(?:[\u2642\u2640]\uFE0F?))?|[\uDDCD\uDDCE\uDDD6\uDDD7\uDD38](?:(?:\uD83C(?:[\uDFFB-\uDFFF](?:\u200D(?:[\u2642\u2640]\uFE0F?))?)|\u200D(?:[\u2642\u2640]\uFE0F?)))?|\uDD3C(?:\u200D(?:[\u2642\u2640]\uFE0F?))?|[\uDD3D\uDD3E\uDD39\uDDD8](?:(?:\uD83C(?:[\uDFFB-\uDFFF](?:\u200D(?:[\u2642\u2640]\uFE0F?))?)|\u200D(?:[\u2642\u2640]\uFE0F?)))?|[\uDD23\uDD70\uDD29\uDD2A\uDD11\uDD17\uDD2D\uDD2B\uDD14\uDD10\uDD28\uDD25\uDD24\uDD12\uDD15\uDD22\uDD2E\uDD27\uDD75\uDD76\uDD74\uDD2F\uDD20\uDD73\uDD13\uDDD0\uDD7A\uDD71\uDD2C\uDD21\uDD16\uDDE1\uDD0E\uDD0D\uDD1D\uDDBE\uDDBF\uDDE0\uDDB7\uDDB4\uDD3A\uDDB0\uDDB1\uDDB3\uDDB2\uDD8D\uDDA7\uDDAE\uDD8A\uDD9D\uDD81\uDD84\uDD93\uDD8C\uDD99\uDD92\uDD8F\uDD9B\uDD94\uDD87\uDDA5\uDDA6\uDDA8\uDD98\uDDA1\uDD83\uDD85\uDD86\uDDA2\uDD89\uDDA9\uDD9A\uDD9C\uDD8E\uDD95\uDD96\uDD88\uDD8B\uDD97\uDD82\uDD9F\uDDA0\uDD40\uDD6D\uDD5D\uDD65\uDD51\uDD54\uDD55\uDD52\uDD6C\uDD66\uDDC4\uDDC5\uDD5C\uDD50\uDD56\uDD68\uDD6F\uDD5E\uDDC7\uDDC0\uDD69\uDD53\uDD6A\uDD59\uDDC6\uDD5A\uDD58\uDD63\uDD57\uDDC8\uDDC2\uDD6B\uDD6E\uDD5F-\uDD61\uDD80\uDD9E\uDD90\uDD91\uDDAA\uDDC1\uDD67\uDD5B\uDD42\uDD43\uDD64\uDDC3\uDDC9\uDDCA\uDD62\uDD44\uDDED\uDDF1\uDDBD\uDDBC\uDE82\uDDF3\uDE90\uDDE8\uDDE7\uDD47-\uDD49\uDD4E\uDD4F\uDD4D\uDD4A\uDD4B\uDD45\uDD3F\uDD4C\uDE80\uDE81\uDDFF\uDDE9\uDDF8\uDDF5\uDDF6\uDD7D\uDD7C\uDDBA\uDDE3-\uDDE6\uDD7B\uDE71-\uDE73\uDD7E\uDD7F\uDE70\uDDE2\uDE95\uDD41\uDDEE\uDE94\uDDFE\uDE93\uDDAF\uDDF0\uDDF2\uDDEA-\uDDEC\uDE78-\uDE7A\uDE91\uDE92\uDDF4\uDDF7\uDDF9-\uDDFD\uDDEF])|[\u263A\u2639\u2620\u2763\u2764]\uFE0F?|\u270B(?:\uD83C[\uDFFB-\uDFFF])?|[\u270C\u261D](?:(?:\uD83C[\uDFFB-\uDFFF]|\uFE0F))?|\u270A(?:\uD83C[\uDFFB-\uDFFF])?|\u270D(?:(?:\uD83C[\uDFFB-\uDFFF]|\uFE0F))?|\uD83C(?:\uDF85(?:\uD83C[\uDFFB-\uDFFF])?|\uDFC3(?:(?:\uD83C(?:[\uDFFB-\uDFFF](?:\u200D(?:[\u2642\u2640]\uFE0F?))?)|\u200D(?:[\u2642\u2640]\uFE0F?)))?|[\uDFC7\uDFC2](?:\uD83C[\uDFFB-\uDFFF])?|\uDFCC(?:(?:\uFE0F(?:\u200D(?:[\u2642\u2640]\uFE0F?))?|\uD83C(?:[\uDFFB-\uDFFF](?:\u200D(?:[\u2642\u2640]\uFE0F?))?)|\u200D(?:[\u2642\u2640]\uFE0F?)))?|[\uDFC4\uDFCA](?:(?:\uD83C(?:[\uDFFB-\uDFFF](?:\u200D(?:[\u2642\u2640]\uFE0F?))?)|\u200D(?:[\u2642\u2640]\uFE0F?)))?|\uDFCB(?:(?:\uFE0F(?:\u200D(?:[\u2642\u2640]\uFE0F?))?|\uD83C(?:[\uDFFB-\uDFFF](?:\u200D(?:[\u2642\u2640]\uFE0F?))?)|\u200D(?:[\u2642\u2640]\uFE0F?)))?|[\uDFF5\uDF36\uDF7D\uDFD4-\uDFD6\uDFDC-\uDFDF\uDFDB\uDFD7\uDFD8\uDFDA\uDFD9\uDFCE\uDFCD\uDF21\uDF24-\uDF2C\uDF97\uDF9F\uDF96\uDF99-\uDF9B\uDF9E\uDFF7\uDD70\uDD71\uDD7E\uDD7F\uDE02\uDE37]\uFE0F?|\uDFF4(?:(?:\u200D\u2620\uFE0F?|\uDB40\uDC67\uDB40\uDC62\uDB40(?:\uDC65\uDB40\uDC6E\uDB40\uDC67\uDB40\uDC7F|\uDC73\uDB40\uDC63\uDB40\uDC74\uDB40\uDC7F|\uDC77\uDB40\uDC6C\uDB40\uDC73\uDB40\uDC7F)))?|\uDFF3(?:(?:\uFE0F(?:\u200D\uD83C\uDF08)?|\u200D\uD83C\uDF08))?|\uDDE6\uD83C[\uDDE8-\uDDEC\uDDEE\uDDF1\uDDF2\uDDF4\uDDF6-\uDDFA\uDDFC\uDDFD\uDDFF]|\uDDE7\uD83C[\uDDE6\uDDE7\uDDE9-\uDDEF\uDDF1-\uDDF4\uDDF6-\uDDF9\uDDFB\uDDFC\uDDFE\uDDFF]|\uDDE8\uD83C[\uDDE6\uDDE8\uDDE9\uDDEB-\uDDEE\uDDF0-\uDDF5\uDDF7\uDDFA-\uDDFF]|\uDDE9\uD83C[\uDDEA\uDDEC\uDDEF\uDDF0\uDDF2\uDDF4\uDDFF]|\uDDEA\uD83C[\uDDE6\uDDE8\uDDEA\uDDEC\uDDED\uDDF7-\uDDFA]|\uDDEB\uD83C[\uDDEE-\uDDF0\uDDF2\uDDF4\uDDF7]|\uDDEC\uD83C[\uDDE6\uDDE7\uDDE9-\uDDEE\uDDF1-\uDDF3\uDDF5-\uDDFA\uDDFC\uDDFE]|\uDDED\uD83C[\uDDF0\uDDF2\uDDF3\uDDF7\uDDF9\uDDFA]|\uDDEE\uD83C[\uDDE8-\uDDEA\uDDF1-\uDDF4\uDDF6-\uDDF9]|\uDDEF\uD83C[\uDDEA\uDDF2\uDDF4\uDDF5]|\uDDF0\uD83C[\uDDEA\uDDEC-\uDDEE\uDDF2\uDDF3\uDDF5\uDDF7\uDDFC\uDDFE\uDDFF]|\uDDF1\uD83C[\uDDE6-\uDDE8\uDDEE\uDDF0\uDDF7-\uDDFB\uDDFE]|\uDDF2\uD83C[\uDDE6\uDDE8-\uDDED\uDDF0-\uDDFF]|\uDDF3\uD83C[\uDDE6\uDDE8\uDDEA-\uDDEC\uDDEE\uDDF1\uDDF4\uDDF5\uDDF7\uDDFA\uDDFF]|\uDDF4\uD83C\uDDF2|\uDDF5\uD83C[\uDDE6\uDDEA-\uDDED\uDDF0-\uDDF3\uDDF7-\uDDF9\uDDFC\uDDFE]|\uDDF6\uD83C\uDDE6|\uDDF7\uD83C[\uDDEA\uDDF4\uDDF8\uDDFA\uDDFC]|\uDDF8\uD83C[\uDDE6-\uDDEA\uDDEC-\uDDF4\uDDF7-\uDDF9\uDDFB\uDDFD-\uDDFF]|\uDDF9\uD83C[\uDDE6\uDDE8\uDDE9\uDDEB-\uDDED\uDDEF-\uDDF4\uDDF7\uDDF9\uDDFB\uDDFC\uDDFF]|\uDDFA\uD83C[\uDDE6\uDDEC\uDDF2\uDDF3\uDDF8\uDDFE\uDDFF]|\uDDFB\uD83C[\uDDE6\uDDE8\uDDEA\uDDEC\uDDEE\uDDF3\uDDFA]|\uDDFC\uD83C[\uDDEB\uDDF8]|\uDDFD\uD83C\uDDF0|\uDDFE\uD83C[\uDDEA\uDDF9]|\uDDFF\uD83C[\uDDE6\uDDF2\uDDFC]|[\uDFFB-\uDFFF\uDF38-\uDF3C\uDF37\uDF31-\uDF35\uDF3E-\uDF43\uDF47-\uDF53\uDF45\uDF46\uDF3D\uDF44\uDF30\uDF5E\uDF56\uDF57\uDF54\uDF5F\uDF55\uDF2D-\uDF2F\uDF73\uDF72\uDF7F\uDF71\uDF58-\uDF5D\uDF60\uDF62-\uDF65\uDF61\uDF66-\uDF6A\uDF82\uDF70\uDF6B-\uDF6F\uDF7C\uDF75\uDF76\uDF7E\uDF77-\uDF7B\uDF74\uDFFA\uDF0D-\uDF10\uDF0B\uDFE0-\uDFE6\uDFE8-\uDFED\uDFEF\uDFF0\uDF01\uDF03-\uDF07\uDF09\uDFA0-\uDFA2\uDFAA\uDF11-\uDF20\uDF0C\uDF00\uDF08\uDF02\uDF0A\uDF83\uDF84\uDF86-\uDF8B\uDF8D-\uDF91\uDF80\uDF81\uDFAB\uDFC6\uDFC5\uDFC0\uDFD0\uDFC8\uDFC9\uDFBE\uDFB3\uDFCF\uDFD1-\uDFD3\uDFF8\uDFA3\uDFBD\uDFBF\uDFAF\uDFB1\uDFAE\uDFB0\uDFB2\uDCCF\uDC04\uDFB4\uDFAD\uDFA8\uDF92\uDFA9\uDF93\uDFBC\uDFB5\uDFB6\uDFA4\uDFA7\uDFB7-\uDFBB\uDFA5\uDFAC\uDFEE\uDFF9\uDFE7\uDFA6\uDD8E\uDD91-\uDD9A\uDE01\uDE36\uDE2F\uDE50\uDE39\uDE1A\uDE32\uDE51\uDE38\uDE34\uDE33\uDE3A\uDE35\uDFC1\uDF8C])|\u26F7\uFE0F?|\u26F9(?:(?:\uFE0F(?:\u200D(?:[\u2642\u2640]\uFE0F?))?|\uD83C(?:[\uDFFB-\uDFFF](?:\u200D(?:[\u2642\u2640]\uFE0F?))?)|\u200D(?:[\u2642\u2640]\uFE0F?)))?|[\u2618\u26F0\u26E9\u2668\u26F4\u2708\u23F1\u23F2\u2600\u2601\u26C8\u2602\u26F1\u2744\u2603\u2604\u26F8\u2660\u2665\u2666\u2663\u265F\u26D1\u260E\u2328\u2709\u270F\u2712\u2702\u26CF\u2692\u2694\u2699\u2696\u26D3\u2697\u26B0\u26B1\u26A0\u2622\u2623\u2B06\u2197\u27A1\u2198\u2B07\u2199\u2B05\u2196\u2195\u2194\u21A9\u21AA\u2934\u2935\u269B\u2721\u2638\u262F\u271D\u2626\u262A\u262E\u25B6\u23ED\u23EF\u25C0\u23EE\u23F8-\u23FA\u23CF\u2640\u2642\u2695\u267E\u267B\u269C\u2611\u2714\u2716\u303D\u2733\u2734\u2747\u203C\u2049\u3030\u00A9\u00AE\u2122]\uFE0F?|[\u0023\u002A\u0030-\u0039](?:\uFE0F\u20E3|\u20E3)|[\u2139\u24C2\u3297\u3299\u25FC\u25FB\u25AA\u25AB]\uFE0F?|[\u2615\u26EA\u26F2\u26FA\u26FD\u2693\u26F5\u231B\u23F3\u231A\u23F0\u2B50\u26C5\u2614\u26A1\u26C4\u2728\u26BD\u26BE\u26F3\u267F\u26D4\u2648-\u2653\u26CE\u23E9-\u23EC\u2B55\u2705\u274C\u274E\u2795-\u2797\u27B0\u27BF\u2753-\u2755\u2757\u26AB\u26AA\u2B1B\u2B1C\u25FE\u25FD])"; } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive.Common/Regexes/HashtagRegexes.cs b/src/BirdsiteLive.Common/Regexes/HashtagRegexes.cs index b6d9d00..257336c 100644 --- a/src/BirdsiteLive.Common/Regexes/HashtagRegexes.cs +++ b/src/BirdsiteLive.Common/Regexes/HashtagRegexes.cs @@ -1,10 +1,12 @@ -using System.Text.RegularExpressions; +using System.Text.RegularExpressions; namespace BirdsiteLive.Common.Regexes { public class HashtagRegexes { public static readonly Regex HashtagName = new Regex(@"^[a-zA-Z0-9_]+$"); - public static readonly Regex Hashtag = new Regex(@"(.?)#([a-zA-Z0-9_]+)(\s|$|[\[\]<>.,;:!?/|-])"); + public static readonly Regex Hashtag = new Regex( + @"(.?)#([a-zA-Z0-9_]+)(\s|$|[\[\]<>.,;:!?/|-])" + ); } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive.Common/Regexes/HeaderRegexes.cs b/src/BirdsiteLive.Common/Regexes/HeaderRegexes.cs index b98818c..77e5995 100644 --- a/src/BirdsiteLive.Common/Regexes/HeaderRegexes.cs +++ b/src/BirdsiteLive.Common/Regexes/HeaderRegexes.cs @@ -1,4 +1,4 @@ -using System.Text.RegularExpressions; +using System.Text.RegularExpressions; namespace BirdsiteLive.Common.Regexes { @@ -6,4 +6,4 @@ namespace BirdsiteLive.Common.Regexes { public static readonly Regex HeaderSignature = new Regex(@"^([a-zA-Z0-9]+)=""(.+)""$"); } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive.Common/Regexes/UrlRegexes.cs b/src/BirdsiteLive.Common/Regexes/UrlRegexes.cs index 1f2b279..7d750ae 100644 --- a/src/BirdsiteLive.Common/Regexes/UrlRegexes.cs +++ b/src/BirdsiteLive.Common/Regexes/UrlRegexes.cs @@ -1,9 +1,11 @@ -using System.Text.RegularExpressions; +using System.Text.RegularExpressions; namespace BirdsiteLive.Common.Regexes { public class UrlRegexes { - public static readonly Regex Url = new Regex(@"(.?)(((http|ftp|https):\/\/)[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&:/~\+#]*[\w\-\@?^=%&/~\+#])?)"); + public static readonly Regex Url = new Regex( + @"(.?)(((http|ftp|https):\/\/)[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&:/~\+#]*[\w\-\@?^=%&/~\+#])?)" + ); } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive.Common/Regexes/UserRegexes.cs b/src/BirdsiteLive.Common/Regexes/UserRegexes.cs index c20a544..3c0c823 100644 --- a/src/BirdsiteLive.Common/Regexes/UserRegexes.cs +++ b/src/BirdsiteLive.Common/Regexes/UserRegexes.cs @@ -1,10 +1,12 @@ -using System.Text.RegularExpressions; +using System.Text.RegularExpressions; namespace BirdsiteLive.Common.Regexes { public class UserRegexes { public static readonly Regex TwitterAccount = new Regex(@"^[a-zA-Z0-9_]+$"); - public static readonly Regex Mention = new Regex(@"(.?)@([a-zA-Z0-9_]+)(\s|$|[\[\]<>,;:!?/|-]|(. ))"); + public static readonly Regex Mention = new Regex( + @"(.?)@([a-zA-Z0-9_]+)(\s|$|[\[\]<>,;:!?/|-]|(. ))" + ); } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive.Common/Settings/DbSettings.cs b/src/BirdsiteLive.Common/Settings/DbSettings.cs index b70fba1..5fca9b7 100644 --- a/src/BirdsiteLive.Common/Settings/DbSettings.cs +++ b/src/BirdsiteLive.Common/Settings/DbSettings.cs @@ -1,4 +1,4 @@ -namespace BirdsiteLive.Common.Settings +namespace BirdsiteLive.Common.Settings { public class DbSettings { @@ -8,4 +8,4 @@ public string User { get; set; } public string Password { get; set; } } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive.Common/Settings/InstanceSettings.cs b/src/BirdsiteLive.Common/Settings/InstanceSettings.cs index 73cc7ee..9df131c 100644 --- a/src/BirdsiteLive.Common/Settings/InstanceSettings.cs +++ b/src/BirdsiteLive.Common/Settings/InstanceSettings.cs @@ -1,4 +1,4 @@ -namespace BirdsiteLive.Common.Settings +namespace BirdsiteLive.Common.Settings { public class InstanceSettings { diff --git a/src/BirdsiteLive.Common/Settings/LogsSettings.cs b/src/BirdsiteLive.Common/Settings/LogsSettings.cs index 4919417..bcec8fd 100644 --- a/src/BirdsiteLive.Common/Settings/LogsSettings.cs +++ b/src/BirdsiteLive.Common/Settings/LogsSettings.cs @@ -1,8 +1,8 @@ -namespace BirdsiteLive.Common.Settings +namespace BirdsiteLive.Common.Settings { public class LogsSettings { public string Type { get; set; } public string InstrumentationKey { get; set; } } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive.Common/Settings/ModerationSettings.cs b/src/BirdsiteLive.Common/Settings/ModerationSettings.cs index ad9fd54..5d29781 100644 --- a/src/BirdsiteLive.Common/Settings/ModerationSettings.cs +++ b/src/BirdsiteLive.Common/Settings/ModerationSettings.cs @@ -1,4 +1,4 @@ -namespace BirdsiteLive.Common.Settings +namespace BirdsiteLive.Common.Settings { public class ModerationSettings { @@ -7,4 +7,4 @@ public string TwitterAccountsWhiteListing { get; set; } public string TwitterAccountsBlackListing { get; set; } } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive.Common/Settings/TwitterSettings.cs b/src/BirdsiteLive.Common/Settings/TwitterSettings.cs index 3e9095a..0d88441 100644 --- a/src/BirdsiteLive.Common/Settings/TwitterSettings.cs +++ b/src/BirdsiteLive.Common/Settings/TwitterSettings.cs @@ -1,8 +1,8 @@ -namespace BirdsiteLive.Common.Settings +namespace BirdsiteLive.Common.Settings { public class TwitterSettings { public string ConsumerKey { get; set; } public string ConsumerSecret { get; set; } } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive.Common/Structs/DbTypes.cs b/src/BirdsiteLive.Common/Structs/DbTypes.cs index 767f0f3..b729fa2 100644 --- a/src/BirdsiteLive.Common/Structs/DbTypes.cs +++ b/src/BirdsiteLive.Common/Structs/DbTypes.cs @@ -1,7 +1,7 @@ -namespace BirdsiteLive.Common.Structs +namespace BirdsiteLive.Common.Structs { public struct DbTypes { public static string Postgres = "postgres"; } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive.Cryptography/ASN1.cs b/src/BirdsiteLive.Cryptography/ASN1.cs index cd31579..96f5a9d 100644 --- a/src/BirdsiteLive.Cryptography/ASN1.cs +++ b/src/BirdsiteLive.Cryptography/ASN1.cs @@ -1,8 +1,10 @@ -using System.Linq; +using System.Linq; using System.Security.Cryptography; + using Asn1; -using Asn1Sequence = Asn1.Asn1Sequence; + using Asn1Null = Asn1.Asn1Null; +using Asn1Sequence = Asn1.Asn1Sequence; namespace BirdsiteLive.Cryptography { @@ -46,4 +48,4 @@ namespace BirdsiteLive.Cryptography return result.GetBytes(); } } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive.Cryptography/BirdsiteLive.Cryptography.csproj b/src/BirdsiteLive.Cryptography/BirdsiteLive.Cryptography.csproj index f0d9f4f..263ca43 100644 --- a/src/BirdsiteLive.Cryptography/BirdsiteLive.Cryptography.csproj +++ b/src/BirdsiteLive.Cryptography/BirdsiteLive.Cryptography.csproj @@ -1,7 +1,7 @@ - netstandard2.0 + net6.0 diff --git a/src/BirdsiteLive.Cryptography/MagicKey.cs b/src/BirdsiteLive.Cryptography/MagicKey.cs index 23d478a..78b9e32 100644 --- a/src/BirdsiteLive.Cryptography/MagicKey.cs +++ b/src/BirdsiteLive.Cryptography/MagicKey.cs @@ -1,7 +1,8 @@ -using System; +using System; using System.Collections.Generic; using System.Security.Cryptography; using System.Text; + using Newtonsoft.Json; namespace BirdsiteLive.Cryptography @@ -86,7 +87,8 @@ namespace BirdsiteLive.Cryptography else { _parts = key.Split('.'); - if (_parts[0] != "RSA") throw new Exception("Unknown magic key!"); + if (_parts[0] != "RSA") + throw new Exception("Unknown magic key!"); var rsaParams = new RSAParameters(); rsaParams.Modulus = _decodeBase64Url(_parts[1]); @@ -102,18 +104,37 @@ namespace BirdsiteLive.Cryptography var rsa = RSA.Create(); rsa.KeySize = 2048; - return new MagicKey(JsonConvert.SerializeObject(RSAKeyParms.From(rsa.ExportParameters(true)))); + return new MagicKey( + JsonConvert.SerializeObject(RSAKeyParms.From(rsa.ExportParameters(true))) + ); } - public byte[] BuildSignedData(string data, string dataType, string encoding, string algorithm) + public byte[] BuildSignedData( + string data, + string dataType, + string encoding, + string algorithm + ) { - var sig = data + "." + _encodeBase64Url(Encoding.UTF8.GetBytes(dataType)) + "." + _encodeBase64Url(Encoding.UTF8.GetBytes(encoding)) + "." + _encodeBase64Url(Encoding.UTF8.GetBytes(algorithm)); + var sig = + data + + "." + + _encodeBase64Url(Encoding.UTF8.GetBytes(dataType)) + + "." + + _encodeBase64Url(Encoding.UTF8.GetBytes(encoding)) + + "." + + _encodeBase64Url(Encoding.UTF8.GetBytes(algorithm)); return Encoding.UTF8.GetBytes(sig); } public bool Verify(string signature, byte[] data) { - return _rsa.VerifyData(data, _decodeBase64Url(signature), HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); + return _rsa.VerifyData( + data, + _decodeBase64Url(signature), + HashAlgorithmName.SHA256, + RSASignaturePadding.Pkcs1 + ); } public byte[] Sign(byte[] data) @@ -140,7 +161,10 @@ namespace BirdsiteLive.Cryptography public string PrivateKey { - get { return JsonConvert.SerializeObject(RSAKeyParms.From(_rsa.ExportParameters(true))); } + get + { + return JsonConvert.SerializeObject(RSAKeyParms.From(_rsa.ExportParameters(true))); + } } public string PublicKey @@ -149,8 +173,13 @@ namespace BirdsiteLive.Cryptography { var parms = _rsa.ExportParameters(false); - return string.Join(".", "RSA", _encodeBase64Url(parms.Modulus), _encodeBase64Url(parms.Exponent)); + return string.Join( + ".", + "RSA", + _encodeBase64Url(parms.Modulus), + _encodeBase64Url(parms.Exponent) + ); } } } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive.Cryptography/RsaGenerator.cs b/src/BirdsiteLive.Cryptography/RsaGenerator.cs index 5763c54..08fe03b 100644 --- a/src/BirdsiteLive.Cryptography/RsaGenerator.cs +++ b/src/BirdsiteLive.Cryptography/RsaGenerator.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.IO; using System.Security.Cryptography; @@ -13,7 +13,7 @@ namespace BirdsiteLive.Cryptography public string GetRsa() { var rsa = RSA.Create(); - + var outputStream = new StringWriter(); var parameters = rsa.ExportParameters(true); using (var stream = new MemoryStream()) @@ -26,7 +26,18 @@ namespace BirdsiteLive.Cryptography innerWriter.Write((byte)0x30); // SEQUENCE EncodeLength(innerWriter, 13); innerWriter.Write((byte)0x06); // OBJECT IDENTIFIER - var rsaEncryptionOid = new byte[] { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 }; + var rsaEncryptionOid = new byte[] + { + 0x2a, + 0x86, + 0x48, + 0x86, + 0xf7, + 0x0d, + 0x01, + 0x01, + 0x01 + }; EncodeLength(innerWriter, rsaEncryptionOid.Length); innerWriter.Write(rsaEncryptionOid); innerWriter.Write((byte)0x05); // NULL @@ -55,7 +66,9 @@ namespace BirdsiteLive.Cryptography writer.Write(innerStream.GetBuffer(), 0, length); } - var base64 = Convert.ToBase64String(stream.GetBuffer(), 0, (int)stream.Length).ToCharArray(); + var base64 = Convert + .ToBase64String(stream.GetBuffer(), 0, (int)stream.Length) + .ToCharArray(); // WriteLine terminates with \r\n, we want only \n outputStream.Write("-----BEGIN PUBLIC KEY-----\n"); for (var i = 0; i < base64.Length; i += 64) @@ -71,7 +84,8 @@ namespace BirdsiteLive.Cryptography private static void EncodeLength(BinaryWriter stream, int length) { - if (length < 0) throw new ArgumentOutOfRangeException("length", "Length must be non-negative"); + if (length < 0) + throw new ArgumentOutOfRangeException("length", "Length must be non-negative"); if (length < 0x80) { // Short form @@ -94,6 +108,5 @@ namespace BirdsiteLive.Cryptography } } } - } } diff --git a/src/BirdsiteLive.Cryptography/RsaKeys.cs b/src/BirdsiteLive.Cryptography/RsaKeys.cs index 0bc4a90..4acbf9f 100644 --- a/src/BirdsiteLive.Cryptography/RsaKeys.cs +++ b/src/BirdsiteLive.Cryptography/RsaKeys.cs @@ -1,11 +1,12 @@ -using Org.BouncyCastle.Crypto; -using Org.BouncyCastle.Crypto.Parameters; -using Org.BouncyCastle.OpenSsl; -using Org.BouncyCastle.Security; using System; using System.IO; using System.Security.Cryptography; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.OpenSsl; +using Org.BouncyCastle.Security; + namespace MyProject.Data.Encryption { public class RSAKeys @@ -19,9 +20,11 @@ namespace MyProject.Data.Encryption { PemReader pr = new PemReader(new StringReader(pem)); AsymmetricCipherKeyPair KeyPair = (AsymmetricCipherKeyPair)pr.ReadObject(); - RSAParameters rsaParams = DotNetUtilities.ToRSAParameters((RsaPrivateCrtKeyParameters)KeyPair.Private); + RSAParameters rsaParams = DotNetUtilities.ToRSAParameters( + (RsaPrivateCrtKeyParameters)KeyPair.Private + ); - RSACryptoServiceProvider csp = new RSACryptoServiceProvider();// cspParams); + RSACryptoServiceProvider csp = new RSACryptoServiceProvider(); // cspParams); csp.ImportParameters(rsaParams); return csp; } @@ -37,7 +40,7 @@ namespace MyProject.Data.Encryption AsymmetricKeyParameter publicKey = (AsymmetricKeyParameter)pr.ReadObject(); RSAParameters rsaParams = DotNetUtilities.ToRSAParameters((RsaKeyParameters)publicKey); - RSACryptoServiceProvider csp = new RSACryptoServiceProvider();// cspParams); + RSACryptoServiceProvider csp = new RSACryptoServiceProvider(); // cspParams); csp.ImportParameters(rsaParams); return csp; } @@ -51,7 +54,8 @@ namespace MyProject.Data.Encryption public static string ExportPrivateKey(RSACryptoServiceProvider csp) { StringWriter outputStream = new StringWriter(); - if (csp.PublicOnly) throw new ArgumentException("CSP does not contain a private key", "csp"); + if (csp.PublicOnly) + throw new ArgumentException("CSP does not contain a private key", "csp"); var parameters = csp.ExportParameters(true); using (var stream = new MemoryStream()) { @@ -74,7 +78,9 @@ namespace MyProject.Data.Encryption writer.Write(innerStream.GetBuffer(), 0, length); } - var base64 = Convert.ToBase64String(stream.GetBuffer(), 0, (int)stream.Length).ToCharArray(); + var base64 = Convert + .ToBase64String(stream.GetBuffer(), 0, (int)stream.Length) + .ToCharArray(); // WriteLine terminates with \r\n, we want only \n outputStream.Write("-----BEGIN RSA PRIVATE KEY-----\n"); // Output as Base64 with lines chopped at 64 characters @@ -109,7 +115,18 @@ namespace MyProject.Data.Encryption innerWriter.Write((byte)0x30); // SEQUENCE EncodeLength(innerWriter, 13); innerWriter.Write((byte)0x06); // OBJECT IDENTIFIER - var rsaEncryptionOid = new byte[] { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 }; + var rsaEncryptionOid = new byte[] + { + 0x2a, + 0x86, + 0x48, + 0x86, + 0xf7, + 0x0d, + 0x01, + 0x01, + 0x01 + }; EncodeLength(innerWriter, rsaEncryptionOid.Length); innerWriter.Write(rsaEncryptionOid); innerWriter.Write((byte)0x05); // NULL @@ -138,7 +155,9 @@ namespace MyProject.Data.Encryption writer.Write(innerStream.GetBuffer(), 0, length); } - var base64 = Convert.ToBase64String(stream.GetBuffer(), 0, (int)stream.Length).ToCharArray(); + var base64 = Convert + .ToBase64String(stream.GetBuffer(), 0, (int)stream.Length) + .ToCharArray(); // WriteLine terminates with \r\n, we want only \n outputStream.Write("-----BEGIN PUBLIC KEY-----\n"); for (var i = 0; i < base64.Length; i += 64) @@ -159,7 +178,8 @@ namespace MyProject.Data.Encryption /// private static void EncodeLength(BinaryWriter stream, int length) { - if (length < 0) throw new ArgumentOutOfRangeException("length", "Length must be non-negative"); + if (length < 0) + throw new ArgumentOutOfRangeException("length", "Length must be non-negative"); if (length < 0x80) { // Short form @@ -189,13 +209,18 @@ namespace MyProject.Data.Encryption /// /// /// - private static void EncodeIntegerBigEndian(BinaryWriter stream, byte[] value, bool forceUnsigned = true) + private static void EncodeIntegerBigEndian( + BinaryWriter stream, + byte[] value, + bool forceUnsigned = true + ) { stream.Write((byte)0x02); // INTEGER var prefixZeros = 0; for (var i = 0; i < value.Length; i++) { - if (value[i] != 0) break; + if (value[i] != 0) + break; prefixZeros++; } if (value.Length - prefixZeros == 0) @@ -222,4 +247,4 @@ namespace MyProject.Data.Encryption } } } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive.Domain/ActivityPubService.cs b/src/BirdsiteLive.Domain/ActivityPubService.cs index 71a1457..aed69fc 100644 --- a/src/BirdsiteLive.Domain/ActivityPubService.cs +++ b/src/BirdsiteLive.Domain/ActivityPubService.cs @@ -1,16 +1,20 @@ -using System; +using System; using System.Linq; using System.Net; using System.Net.Http; using System.Security.Cryptography; using System.Text; using System.Threading.Tasks; + using BirdsiteLive.ActivityPub; using BirdsiteLive.ActivityPub.Converters; using BirdsiteLive.ActivityPub.Models; using BirdsiteLive.Common.Settings; + using Microsoft.Extensions.Logging; + using Newtonsoft.Json; + using Org.BouncyCastle.Bcpg; namespace BirdsiteLive.Domain @@ -18,9 +22,19 @@ namespace BirdsiteLive.Domain public interface IActivityPubService { Task GetUser(string objectId); - Task PostDataAsync(T data, string targetHost, string actorUrl, string inbox = null); - Task PostNewNoteActivity(Note note, string username, string noteId, string targetHost, - string targetInbox); + Task PostDataAsync( + T data, + string targetHost, + string actorUrl, + string inbox = null + ); + Task PostNewNoteActivity( + Note note, + string username, + string noteId, + string targetHost, + string targetInbox + ); Task WebFinger(string account); } @@ -32,7 +46,12 @@ namespace BirdsiteLive.Domain private readonly ILogger _logger; #region Ctor - public ActivityPubService(ICryptoService cryptoService, InstanceSettings instanceSettings, IHttpClientFactory httpClientFactory, ILogger logger) + public ActivityPubService( + ICryptoService cryptoService, + InstanceSettings instanceSettings, + IHttpClientFactory httpClientFactory, + ILogger logger + ) { _cryptoService = cryptoService; _instanceSettings = instanceSettings; @@ -49,11 +68,18 @@ namespace BirdsiteLive.Domain var content = await result.Content.ReadAsStringAsync(); var actor = JsonConvert.DeserializeObject(content); - if (string.IsNullOrWhiteSpace(actor.url)) actor.url = objectId; + if (string.IsNullOrWhiteSpace(actor.url)) + actor.url = objectId; return actor; } - public async Task PostNewNoteActivity(Note note, string username, string noteId, string targetHost, string targetInbox) + public async Task PostNewNoteActivity( + Note note, + string username, + string noteId, + string targetHost, + string targetInbox + ) { try { @@ -70,7 +96,6 @@ namespace BirdsiteLive.Domain type = "Create", actor = actor, published = nowString, - to = note.to, cc = note.cc, apObject = note @@ -80,12 +105,24 @@ namespace BirdsiteLive.Domain } catch (Exception e) { - _logger.LogError(e, "Error sending {Username} post ({NoteId}) to {Host}{Inbox}", username, noteId, targetHost, targetInbox); + _logger.LogError( + e, + "Error sending {Username} post ({NoteId}) to {Host}{Inbox}", + username, + noteId, + targetHost, + targetInbox + ); throw; } } - public async Task PostDataAsync(T data, string targetHost, string actorUrl, string inbox = null) + public async Task PostDataAsync( + T data, + string targetHost, + string actorUrl, + string inbox = null + ) { var usedInbox = $"/inbox"; if (!string.IsNullOrWhiteSpace(inbox)) @@ -98,7 +135,13 @@ namespace BirdsiteLive.Domain var digest = _cryptoService.ComputeSha256Hash(json); - var signature = _cryptoService.SignAndGetSignatureHeader(date, actorUrl, targetHost, digest, usedInbox); + var signature = _cryptoService.SignAndGetSignatureHeader( + date, + actorUrl, + targetHost, + digest, + usedInbox + ); var client = _httpClientFactory.CreateClient(); var httpRequestMessage = new HttpRequestMessage @@ -107,10 +150,10 @@ namespace BirdsiteLive.Domain RequestUri = new Uri($"https://{targetHost}{usedInbox}"), Headers = { - {"Host", targetHost}, - {"Date", httpDate}, - {"Signature", signature}, - {"Digest", $"SHA-256={digest}"} + { "Host", targetHost }, + { "Date", httpDate }, + { "Signature", signature }, + { "Digest", $"SHA-256={digest}" } }, Content = new StringContent(json, Encoding.UTF8, "application/ld+json") }; @@ -123,10 +166,15 @@ namespace BirdsiteLive.Domain public async Task WebFinger(string account) { var httpClient = _httpClientFactory.CreateClient(); - var result = await httpClient.GetAsync("https://" + account.Split('@')[1] + "/.well-known/webfinger?resource=acct:" + account); + var result = await httpClient.GetAsync( + "https://" + + account.Split('@')[1] + + "/.well-known/webfinger?resource=acct:" + + account + ); var content = await result.Content.ReadAsStringAsync(); return JsonConvert.DeserializeObject(content); } } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive.Domain/BirdsiteLive.Domain.csproj b/src/BirdsiteLive.Domain/BirdsiteLive.Domain.csproj index 8c601b4..d931f9e 100644 --- a/src/BirdsiteLive.Domain/BirdsiteLive.Domain.csproj +++ b/src/BirdsiteLive.Domain/BirdsiteLive.Domain.csproj @@ -1,7 +1,7 @@ - netstandard2.0 + net6.0 diff --git a/src/BirdsiteLive.Domain/BusinessUseCases/ProcessFollowUser.cs b/src/BirdsiteLive.Domain/BusinessUseCases/ProcessFollowUser.cs index c6618d9..5fff80d 100644 --- a/src/BirdsiteLive.Domain/BusinessUseCases/ProcessFollowUser.cs +++ b/src/BirdsiteLive.Domain/BusinessUseCases/ProcessFollowUser.cs @@ -1,11 +1,19 @@ -using System.Threading.Tasks; +using System.Threading.Tasks; + using BirdsiteLive.DAL.Contracts; namespace BirdsiteLive.Domain.BusinessUseCases { public interface IProcessFollowUser { - Task ExecuteAsync(string followerUsername, string followerDomain, string twitterUsername, string followerInbox, string sharedInbox, string followerActorId); + Task ExecuteAsync( + string followerUsername, + string followerDomain, + string twitterUsername, + string followerInbox, + string sharedInbox, + string followerActorId + ); } public class ProcessFollowUser : IProcessFollowUser @@ -21,13 +29,26 @@ namespace BirdsiteLive.Domain.BusinessUseCases } #endregion - public async Task ExecuteAsync(string followerUsername, string followerDomain, string twitterUsername, string followerInbox, string sharedInbox, string followerActorId) + public async Task ExecuteAsync( + string followerUsername, + string followerDomain, + string twitterUsername, + string followerInbox, + string sharedInbox, + string followerActorId + ) { // Get Follower and Twitter Users var follower = await _followerDal.GetFollowerAsync(followerUsername, followerDomain); if (follower == null) { - await _followerDal.CreateFollowerAsync(followerUsername, followerDomain, followerInbox, sharedInbox, followerActorId); + await _followerDal.CreateFollowerAsync( + followerUsername, + followerDomain, + followerInbox, + sharedInbox, + followerActorId + ); follower = await _followerDal.GetFollowerAsync(followerUsername, followerDomain); } @@ -40,14 +61,14 @@ namespace BirdsiteLive.Domain.BusinessUseCases // Update Follower var twitterUserId = twitterUser.Id; - if(!follower.Followings.Contains(twitterUserId)) + if (!follower.Followings.Contains(twitterUserId)) follower.Followings.Add(twitterUserId); - if(!follower.FollowingsSyncStatus.ContainsKey(twitterUserId)) + if (!follower.FollowingsSyncStatus.ContainsKey(twitterUserId)) follower.FollowingsSyncStatus.Add(twitterUserId, -1); - + // Save Follower await _followerDal.UpdateFollowerAsync(follower); } } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive.Domain/BusinessUseCases/ProcessUnfollowUser.cs b/src/BirdsiteLive.Domain/BusinessUseCases/ProcessUnfollowUser.cs index a8a53b4..72919c5 100644 --- a/src/BirdsiteLive.Domain/BusinessUseCases/ProcessUnfollowUser.cs +++ b/src/BirdsiteLive.Domain/BusinessUseCases/ProcessUnfollowUser.cs @@ -1,5 +1,6 @@ -using System.Linq; +using System.Linq; using System.Threading.Tasks; + using BirdsiteLive.DAL.Contracts; namespace BirdsiteLive.Domain.BusinessUseCases @@ -22,14 +23,20 @@ namespace BirdsiteLive.Domain.BusinessUseCases } #endregion - public async Task ExecuteAsync(string followerUsername, string followerDomain, string twitterUsername) + public async Task ExecuteAsync( + string followerUsername, + string followerDomain, + string twitterUsername + ) { // Get Follower and Twitter Users var follower = await _followerDal.GetFollowerAsync(followerUsername, followerDomain); - if (follower == null) return; + if (follower == null) + return; var twitterUser = await _twitterUserDal.GetTwitterUserAsync(twitterUsername); - if (twitterUser == null) return; + if (twitterUser == null) + return; // Update Follower var twitterUserId = twitterUser.Id; @@ -43,12 +50,12 @@ namespace BirdsiteLive.Domain.BusinessUseCases if (follower.Followings.Any()) await _followerDal.UpdateFollowerAsync(follower); else - await _followerDal.DeleteFollowerAsync(followerUsername, followerDomain); - + await _followerDal.DeleteFollowerAsync(followerUsername, followerDomain); + // Check if TwitterUser has still followers var followers = await _followerDal.GetFollowersAsync(twitterUser.Id); if (!followers.Any()) await _twitterUserDal.DeleteTwitterUserAsync(twitterUsername); } } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive.Domain/CryptoService.cs b/src/BirdsiteLive.Domain/CryptoService.cs index 01e7d63..66a8d07 100644 --- a/src/BirdsiteLive.Domain/CryptoService.cs +++ b/src/BirdsiteLive.Domain/CryptoService.cs @@ -1,6 +1,7 @@ -using System; +using System; using System.Security.Cryptography; using System.Text; + using BirdsiteLive.Domain.Factories; namespace BirdsiteLive.Domain @@ -8,7 +9,13 @@ namespace BirdsiteLive.Domain public interface ICryptoService { string GetUserPem(string id); - string SignAndGetSignatureHeader(DateTime date, string actor, string host, string digest, string inbox); + string SignAndGetSignatureHeader( + DateTime date, + string actor, + string host, + string digest, + string inbox + ); string ComputeSha256Hash(string data); } @@ -29,13 +36,19 @@ namespace BirdsiteLive.Domain } /// - /// + /// /// /// /// in the form of https://domain.io/actor /// in the form of domain.io /// - public string SignAndGetSignatureHeader(DateTime date, string actor, string targethost, string digest, string inbox) + public string SignAndGetSignatureHeader( + DateTime date, + string actor, + string targethost, + string digest, + string inbox + ) { var usedInbox = "/inbox"; if (!string.IsNullOrWhiteSpace(inbox)) @@ -43,24 +56,30 @@ namespace BirdsiteLive.Domain var httpDate = date.ToString("r"); - var signedString = $"(request-target): post {usedInbox}\nhost: {targethost}\ndate: {httpDate}\ndigest: SHA-256={digest}"; + var signedString = + $"(request-target): post {usedInbox}\nhost: {targethost}\ndate: {httpDate}\ndigest: SHA-256={digest}"; var signedStringBytes = Encoding.UTF8.GetBytes(signedString); var signature = _magicKeyFactory.GetMagicKey().Sign(signedStringBytes); var sig64 = Convert.ToBase64String(signature); - var header = "keyId=\"" + actor + "\",algorithm=\"rsa-sha256\",headers=\"(request-target) host date digest\",signature=\"" + sig64 + "\""; + var header = + "keyId=\"" + + actor + + "\",algorithm=\"rsa-sha256\",headers=\"(request-target) host date digest\",signature=\"" + + sig64 + + "\""; return header; } public string ComputeSha256Hash(string data) { - // Create a SHA256 + // Create a SHA256 using (SHA256 sha256Hash = SHA256.Create()) { - // ComputeHash - returns byte array + // ComputeHash - returns byte array byte[] bytes = sha256Hash.ComputeHash(Encoding.UTF8.GetBytes(data)); return Convert.ToBase64String(bytes); } } } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive.Domain/Factories/MagicKeyFactory.cs b/src/BirdsiteLive.Domain/Factories/MagicKeyFactory.cs index 990c5f4..0f4bca5 100644 --- a/src/BirdsiteLive.Domain/Factories/MagicKeyFactory.cs +++ b/src/BirdsiteLive.Domain/Factories/MagicKeyFactory.cs @@ -1,4 +1,5 @@ -using System.IO; +using System.IO; + using BirdsiteLive.Cryptography; namespace BirdsiteLive.Domain.Factories @@ -14,16 +15,14 @@ namespace BirdsiteLive.Domain.Factories private static MagicKey _magicKey; #region Ctor - public MagicKeyFactory() - { - - } + public MagicKeyFactory() { } #endregion public MagicKey GetMagicKey() { //Cached key - if (_magicKey != null) return _magicKey; + if (_magicKey != null) + return _magicKey; //Generate key if needed if (!File.Exists(Path)) @@ -38,4 +37,4 @@ namespace BirdsiteLive.Domain.Factories return _magicKey; } } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive.Domain/Repository/ModerationRepository.cs b/src/BirdsiteLive.Domain/Repository/ModerationRepository.cs index 071654a..58a9efa 100644 --- a/src/BirdsiteLive.Domain/Repository/ModerationRepository.cs +++ b/src/BirdsiteLive.Domain/Repository/ModerationRepository.cs @@ -1,7 +1,8 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Text.RegularExpressions; + using BirdsiteLive.Common.Settings; using BirdsiteLive.Domain.Tools; @@ -38,8 +39,12 @@ namespace BirdsiteLive.Domain.Repository var parsedFollowersWhiteListing = PatternsParser.Parse(settings.FollowersWhiteListing); var parsedFollowersBlackListing = PatternsParser.Parse(settings.FollowersBlackListing); - var parsedTwitterAccountsWhiteListing = PatternsParser.Parse(settings.TwitterAccountsWhiteListing); - var parsedTwitterAccountsBlackListing = PatternsParser.Parse(settings.TwitterAccountsBlackListing); + var parsedTwitterAccountsWhiteListing = PatternsParser.Parse( + settings.TwitterAccountsWhiteListing + ); + var parsedTwitterAccountsBlackListing = PatternsParser.Parse( + settings.TwitterAccountsBlackListing + ); _followersWhiteListing = parsedFollowersWhiteListing .Select(x => ModerationRegexParser.Parse(ModerationEntityTypeEnum.Follower, x)) @@ -48,10 +53,14 @@ namespace BirdsiteLive.Domain.Repository .Select(x => ModerationRegexParser.Parse(ModerationEntityTypeEnum.Follower, x)) .ToArray(); _twitterAccountsWhiteListing = parsedTwitterAccountsWhiteListing - .Select(x => ModerationRegexParser.Parse(ModerationEntityTypeEnum.TwitterAccount, x)) + .Select( + x => ModerationRegexParser.Parse(ModerationEntityTypeEnum.TwitterAccount, x) + ) .ToArray(); _twitterAccountsBlackListing = parsedTwitterAccountsBlackListing - .Select(x => ModerationRegexParser.Parse(ModerationEntityTypeEnum.TwitterAccount, x)) + .Select( + x => ModerationRegexParser.Parse(ModerationEntityTypeEnum.TwitterAccount, x) + ) .ToArray(); // Set Follower moderation politic @@ -64,9 +73,15 @@ namespace BirdsiteLive.Domain.Repository // Set Twitter account moderation politic if (_twitterAccountsWhiteListing.Any()) - _modMode.Add(ModerationEntityTypeEnum.TwitterAccount, ModerationTypeEnum.WhiteListing); + _modMode.Add( + ModerationEntityTypeEnum.TwitterAccount, + ModerationTypeEnum.WhiteListing + ); else if (_twitterAccountsBlackListing.Any()) - _modMode.Add(ModerationEntityTypeEnum.TwitterAccount, ModerationTypeEnum.BlackListing); + _modMode.Add( + ModerationEntityTypeEnum.TwitterAccount, + ModerationTypeEnum.BlackListing + ); else _modMode.Add(ModerationEntityTypeEnum.TwitterAccount, ModerationTypeEnum.None); } @@ -79,7 +94,8 @@ namespace BirdsiteLive.Domain.Repository public ModeratedTypeEnum CheckStatus(ModerationEntityTypeEnum type, string entity) { - if (_modMode[type] == ModerationTypeEnum.None) return ModeratedTypeEnum.None; + if (_modMode[type] == ModerationTypeEnum.None) + return ModeratedTypeEnum.None; switch (type) { @@ -91,7 +107,7 @@ namespace BirdsiteLive.Domain.Repository throw new NotImplementedException($"Type {type} is not supported"); } - + private ModeratedTypeEnum ProcessFollower(string entity) { var politic = _modMode[ModerationEntityTypeEnum.Follower]; @@ -137,30 +153,40 @@ namespace BirdsiteLive.Domain.Repository private char GetSplitChar(string entry) { var separationChar = '|'; - if (entry.Contains(";")) separationChar = ';'; - else if (entry.Contains(",")) separationChar = ','; + if (entry.Contains(";")) + separationChar = ';'; + else if (entry.Contains(",")) + separationChar = ','; return separationChar; } public IEnumerable GetWhitelistedFollowers() { - return _settings.FollowersWhiteListing.Split(GetSplitChar(_settings.FollowersWhiteListing)); + return _settings.FollowersWhiteListing.Split( + GetSplitChar(_settings.FollowersWhiteListing) + ); } public IEnumerable GetBlacklistedFollowers() { - return _settings.FollowersBlackListing.Split(GetSplitChar(_settings.FollowersBlackListing)); + return _settings.FollowersBlackListing.Split( + GetSplitChar(_settings.FollowersBlackListing) + ); } public IEnumerable GetWhitelistedAccounts() { - return _settings.TwitterAccountsWhiteListing.Split(GetSplitChar(_settings.TwitterAccountsWhiteListing)); + return _settings.TwitterAccountsWhiteListing.Split( + GetSplitChar(_settings.TwitterAccountsWhiteListing) + ); } public IEnumerable GetBlacklistedAccounts() { - return _settings.TwitterAccountsBlackListing.Split(GetSplitChar(_settings.TwitterAccountsBlackListing)); + return _settings.TwitterAccountsBlackListing.Split( + GetSplitChar(_settings.TwitterAccountsBlackListing) + ); } } @@ -184,4 +210,4 @@ namespace BirdsiteLive.Domain.Repository BlackListed = 1, WhiteListed = 2 } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive.Domain/Repository/PublicationRepository.cs b/src/BirdsiteLive.Domain/Repository/PublicationRepository.cs index 042aeb2..6173d27 100644 --- a/src/BirdsiteLive.Domain/Repository/PublicationRepository.cs +++ b/src/BirdsiteLive.Domain/Repository/PublicationRepository.cs @@ -1,4 +1,5 @@ -using System.Linq; +using System.Linq; + using BirdsiteLive.Common.Settings; using BirdsiteLive.Domain.Tools; @@ -25,14 +26,16 @@ namespace BirdsiteLive.Domain.Repository public bool IsUnlisted(string twitterAcct) { - if (_unlistedAccounts == null || !_unlistedAccounts.Any()) return false; + if (_unlistedAccounts == null || !_unlistedAccounts.Any()) + return false; return _unlistedAccounts.Contains(twitterAcct.ToLowerInvariant()); } public bool IsSensitive(string twitterAcct) { - if (_sensitiveAccounts == null || !_sensitiveAccounts.Any()) return false; + if (_sensitiveAccounts == null || !_sensitiveAccounts.Any()) + return false; return _sensitiveAccounts.Contains(twitterAcct.ToLowerInvariant()); } diff --git a/src/BirdsiteLive.Domain/Statistics/ExtractionStatisticsHandler.cs b/src/BirdsiteLive.Domain/Statistics/ExtractionStatisticsHandler.cs index b8ed036..efa4126 100644 --- a/src/BirdsiteLive.Domain/Statistics/ExtractionStatisticsHandler.cs +++ b/src/BirdsiteLive.Domain/Statistics/ExtractionStatisticsHandler.cs @@ -1,4 +1,4 @@ -using System.Threading; +using System.Threading; using System.Timers; namespace BirdsiteLive.Domain.Statistics @@ -57,14 +57,24 @@ namespace BirdsiteLive.Domain.Statistics public ExtractionStatistics GetStatistics() { - return new ExtractionStatistics(_descriptionMentionsExtracted, _statusMentionsExtracted, _lastDescriptionMentionsExtracted, _lastStatusMentionsExtracted); + return new ExtractionStatistics( + _descriptionMentionsExtracted, + _statusMentionsExtracted, + _lastDescriptionMentionsExtracted, + _lastStatusMentionsExtracted + ); } } public class ExtractionStatistics { #region Ctor - public ExtractionStatistics(int mentionsInDescriptionsExtraction, int mentionsInStatusesExtraction, int lastMentionsInDescriptionsExtraction, int lastMentionsInStatusesExtraction) + public ExtractionStatistics( + int mentionsInDescriptionsExtraction, + int mentionsInStatusesExtraction, + int lastMentionsInDescriptionsExtraction, + int lastMentionsInStatusesExtraction + ) { MentionsInDescriptionsExtraction = mentionsInDescriptionsExtraction; MentionsInStatusesExtraction = mentionsInStatusesExtraction; @@ -79,4 +89,4 @@ namespace BirdsiteLive.Domain.Statistics public int LastMentionsInDescriptionsExtraction { get; } public int LastMentionsInStatusesExtraction { get; } } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive.Domain/StatusService.cs b/src/BirdsiteLive.Domain/StatusService.cs index ab33547..0f4a9bf 100644 --- a/src/BirdsiteLive.Domain/StatusService.cs +++ b/src/BirdsiteLive.Domain/StatusService.cs @@ -1,8 +1,9 @@ -using System; +using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text.RegularExpressions; + using BirdsiteLive.ActivityPub; using BirdsiteLive.ActivityPub.Converters; using BirdsiteLive.ActivityPub.Models; @@ -11,6 +12,7 @@ using BirdsiteLive.Domain.Repository; using BirdsiteLive.Domain.Statistics; using BirdsiteLive.Domain.Tools; using BirdsiteLive.Twitter.Models; + using Tweetinvi.Models; using Tweetinvi.Models.Entities; @@ -29,7 +31,12 @@ namespace BirdsiteLive.Domain private readonly IPublicationRepository _publicationRepository; #region Ctor - public StatusService(InstanceSettings instanceSettings, IStatusExtractor statusExtractor, IExtractionStatisticsHandler statisticsHandler, IPublicationRepository publicationRepository) + public StatusService( + InstanceSettings instanceSettings, + IStatusExtractor statusExtractor, + IExtractionStatisticsHandler statisticsHandler, + IPublicationRepository publicationRepository + ) { _instanceSettings = instanceSettings; _statusExtractor = statusExtractor; @@ -41,15 +48,19 @@ namespace BirdsiteLive.Domain public Note GetStatus(string username, ExtractedTweet tweet) { var actorUrl = UrlFactory.GetActorUrl(_instanceSettings.Domain, username); - var noteUrl = UrlFactory.GetNoteUrl(_instanceSettings.Domain, username, tweet.Id.ToString()); + var noteUrl = UrlFactory.GetNoteUrl( + _instanceSettings.Domain, + username, + tweet.Id.ToString() + ); var to = $"{actorUrl}/followers"; var isUnlisted = _publicationRepository.IsUnlisted(username); var cc = new string[0]; if (isUnlisted) - cc = new[] {"https://www.w3.org/ns/activitystreams#Public"}; - + cc = new[] { "https://www.w3.org/ns/activitystreams#Public" }; + string summary = null; var sensitive = _publicationRepository.IsSensitive(username); if (sensitive || tweet.IsSensitive) @@ -63,38 +74,37 @@ namespace BirdsiteLive.Domain if (content.Contains("{RT}") && tweet.IsRetweet) { if (!string.IsNullOrWhiteSpace(tweet.RetweetUrl)) - content = content.Replace("{RT}", - $@"RT"); + content = content.Replace( + "{RT}", + $@"RT" + ); else content = content.Replace("{RT}", "RT"); } string inReplyTo = null; if (tweet.InReplyToStatusId != default) - inReplyTo = $"https://{_instanceSettings.Domain}/users/{tweet.InReplyToAccount.ToLowerInvariant()}/statuses/{tweet.InReplyToStatusId}"; + inReplyTo = + $"https://{_instanceSettings.Domain}/users/{tweet.InReplyToAccount.ToLowerInvariant()}/statuses/{tweet.InReplyToStatusId}"; - if( tweet.QuoteTweetUrl != null ) - content += $@"

RT: {tweet.QuoteTweetUrl}
"; + if (tweet.QuoteTweetUrl != null) + content += + $@"

RT: {tweet.QuoteTweetUrl}
"; var note = new Note { id = noteUrl, - published = tweet.CreatedAt.ToString("s") + "Z", url = noteUrl, attributedTo = actorUrl, - inReplyTo = inReplyTo, - to = new[] { to }, cc = cc, - sensitive = tweet.IsSensitive || sensitive, summary = summary, content = $"

{content}

", attachment = Convert(tweet.Media), tag = extractedTags.tags, - quoteUrl = tweet.QuoteTweetUrl }; @@ -103,16 +113,19 @@ namespace BirdsiteLive.Domain private Attachment[] Convert(ExtractedMedia[] media) { - if(media == null) return new Attachment[0]; - return media.Select(x => - { - return new Attachment + if (media == null) + return new Attachment[0]; + return media + .Select(x => { - type = "Document", - url = x.Url, - mediaType = x.MediaType - }; - }).ToArray(); + return new Attachment + { + type = "Document", + url = x.Url, + mediaType = x.MediaType + }; + }) + .ToArray(); } } } diff --git a/src/BirdsiteLive.Domain/Tools/ModerationRegexParser.cs b/src/BirdsiteLive.Domain/Tools/ModerationRegexParser.cs index 6f4df11..a6cc001 100644 --- a/src/BirdsiteLive.Domain/Tools/ModerationRegexParser.cs +++ b/src/BirdsiteLive.Domain/Tools/ModerationRegexParser.cs @@ -1,6 +1,8 @@ -using System; +using System; using System.Text.RegularExpressions; + using BirdsiteLive.Domain.Repository; + using Org.BouncyCastle.Pkcs; namespace BirdsiteLive.Domain.Tools @@ -25,4 +27,4 @@ namespace BirdsiteLive.Domain.Tools return new Regex($@"^{data}$"); } } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive.Domain/Tools/PatternsParser.cs b/src/BirdsiteLive.Domain/Tools/PatternsParser.cs index bd77c62..5695027 100644 --- a/src/BirdsiteLive.Domain/Tools/PatternsParser.cs +++ b/src/BirdsiteLive.Domain/Tools/PatternsParser.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Linq; namespace BirdsiteLive.Domain.Tools @@ -7,17 +7,20 @@ namespace BirdsiteLive.Domain.Tools { public static string[] Parse(string entry) { - if (string.IsNullOrWhiteSpace(entry)) return new string[0]; + if (string.IsNullOrWhiteSpace(entry)) + return new string[0]; var separationChar = '|'; - if (entry.Contains(";")) separationChar = ';'; - else if (entry.Contains(",")) separationChar = ','; + if (entry.Contains(";")) + separationChar = ';'; + else if (entry.Contains(",")) + separationChar = ','; var splitEntries = entry - .Split(new[] {separationChar}, StringSplitOptions.RemoveEmptyEntries) + .Split(new[] { separationChar }, StringSplitOptions.RemoveEmptyEntries) .Where(x => !string.IsNullOrWhiteSpace(x)) .Select(x => x.ToLowerInvariant().Trim()); return splitEntries.ToArray(); } } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive.Domain/Tools/StatusExtractor.cs b/src/BirdsiteLive.Domain/Tools/StatusExtractor.cs index 4e98baf..5314a8e 100644 --- a/src/BirdsiteLive.Domain/Tools/StatusExtractor.cs +++ b/src/BirdsiteLive.Domain/Tools/StatusExtractor.cs @@ -1,10 +1,12 @@ -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; using System.Text.RegularExpressions; + using BirdsiteLive.ActivityPub.Models; using BirdsiteLive.Common.Regexes; using BirdsiteLive.Common.Settings; using BirdsiteLive.Twitter; + using Microsoft.Extensions.Logging; namespace BirdsiteLive.Domain.Tools @@ -27,7 +29,10 @@ namespace BirdsiteLive.Domain.Tools } #endregion - public (string content, Tag[] tags) Extract(string messageContent, bool extractMentions = true) + public (string content, Tag[] tags) Extract( + string messageContent, + bool extractMentions = true + ) { var tags = new List(); @@ -64,8 +69,11 @@ namespace BirdsiteLive.Domain.Tools secondPart = truncatedUrl.Substring(30); } - messageContent = Regex.Replace(messageContent, Regex.Escape(m.ToString()), - $@"{m.Groups[1]}{protocol}{firstPart}{secondPart}"); + messageContent = Regex.Replace( + messageContent, + Regex.Escape(m.ToString()), + $@"{m.Groups[1]}{protocol}{firstPart}{secondPart}" + ); } // Extract Hashtags @@ -76,7 +84,11 @@ namespace BirdsiteLive.Domain.Tools if (!HashtagRegexes.HashtagName.IsMatch(tag)) { - _logger.LogError("Parsing Hashtag failed: {Tag} on {Content}", tag, messageContent); + _logger.LogError( + "Parsing Hashtag failed: {Tag} on {Content}", + tag, + messageContent + ); continue; } @@ -84,16 +96,21 @@ namespace BirdsiteLive.Domain.Tools if (tags.All(x => x.href != url)) { - tags.Add(new Tag - { - name = $"#{tag}", - href = url, - type = "Hashtag" - }); + tags.Add( + new Tag + { + name = $"#{tag}", + href = url, + type = "Hashtag" + } + ); } - messageContent = Regex.Replace(messageContent, Regex.Escape(m.Groups[0].ToString()), - $@"{m.Groups[1]}#{tag}{m.Groups[3]}"); + messageContent = Regex.Replace( + messageContent, + Regex.Escape(m.Groups[0].ToString()), + $@"{m.Groups[1]}#{tag}{m.Groups[3]}" + ); } // Extract Mentions @@ -106,7 +123,11 @@ namespace BirdsiteLive.Domain.Tools if (!UserRegexes.TwitterAccount.IsMatch(mention)) { - _logger.LogError("Parsing Mention failed: {Mention} on {Content}", mention, messageContent); + _logger.LogError( + "Parsing Mention failed: {Mention} on {Content}", + mention, + messageContent + ); continue; } @@ -115,26 +136,32 @@ namespace BirdsiteLive.Domain.Tools if (tags.All(x => x.href != url)) { - tags.Add(new Tag - { - name = name, - href = url, - type = "Mention" - }); + tags.Add( + new Tag + { + name = name, + href = url, + type = "Mention" + } + ); } - messageContent = Regex.Replace(messageContent, Regex.Escape(m.Groups[0].ToString()), - $@"{m.Groups[1]}@{mention}{m.Groups[3]}"); + messageContent = Regex.Replace( + messageContent, + Regex.Escape(m.Groups[0].ToString()), + $@"{m.Groups[1]}@{mention}{m.Groups[3]}" + ); } } return (messageContent.Trim(), tags.ToArray()); } - + private IEnumerable OrderByLength(MatchCollection matches) { var result = new List(); - foreach (Match m in matches) result.Add(m); + foreach (Match m in matches) + result.Add(m); result = result .OrderBy(x => x.Length) @@ -145,4 +172,4 @@ namespace BirdsiteLive.Domain.Tools return result; } } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive.Domain/UserService.cs b/src/BirdsiteLive.Domain/UserService.cs index c3817ed..a221a9d 100644 --- a/src/BirdsiteLive.Domain/UserService.cs +++ b/src/BirdsiteLive.Domain/UserService.cs @@ -1,10 +1,11 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Security.Cryptography; using System.Text; using System.Threading.Tasks; + using BirdsiteLive.ActivityPub; using BirdsiteLive.ActivityPub.Converters; using BirdsiteLive.ActivityPub.Models; @@ -18,6 +19,7 @@ using BirdsiteLive.Domain.Statistics; using BirdsiteLive.Domain.Tools; using BirdsiteLive.Twitter; using BirdsiteLive.Twitter.Models; + using Tweetinvi.Core.Exceptions; using Tweetinvi.Models; @@ -26,8 +28,24 @@ namespace BirdsiteLive.Domain public interface IUserService { Actor GetUser(TwitterUser twitterUser); - Task FollowRequestedAsync(string signature, string method, string path, string queryString, Dictionary requestHeaders, ActivityFollow activity, string body); - Task UndoFollowRequestedAsync(string signature, string method, string path, string queryString, Dictionary requestHeaders, ActivityUndoFollow activity, string body); + Task FollowRequestedAsync( + string signature, + string method, + string path, + string queryString, + Dictionary requestHeaders, + ActivityFollow activity, + string body + ); + Task UndoFollowRequestedAsync( + string signature, + string method, + string path, + string queryString, + Dictionary requestHeaders, + ActivityUndoFollow activity, + string body + ); Task SendRejectFollowAsync(ActivityFollow activity, string followerHost); } @@ -50,7 +68,18 @@ namespace BirdsiteLive.Domain private readonly IFollowersDal _followerDal; #region Ctor - public UserService(InstanceSettings instanceSettings, ICryptoService cryptoService, IActivityPubService activityPubService, IProcessFollowUser processFollowUser, IProcessUndoFollowUser processUndoFollowUser, IStatusExtractor statusExtractor, IExtractionStatisticsHandler statisticsHandler, ITwitterUserService twitterUserService, IModerationRepository moderationRepository, IFollowersDal followerDal) + public UserService( + InstanceSettings instanceSettings, + ICryptoService cryptoService, + IActivityPubService activityPubService, + IProcessFollowUser processFollowUser, + IProcessUndoFollowUser processUndoFollowUser, + IStatusExtractor statusExtractor, + IExtractionStatisticsHandler statisticsHandler, + ITwitterUserService twitterUserService, + IModerationRepository moderationRepository, + IFollowersDal followerDal + ) { _instanceSettings = instanceSettings; _cryptoService = cryptoService; @@ -74,44 +103,60 @@ namespace BirdsiteLive.Domain var description = twitterUser.Description; if (!string.IsNullOrWhiteSpace(description)) { - var extracted = _statusExtractor.Extract(description, _instanceSettings.ResolveMentionsInProfiles); + var extracted = _statusExtractor.Extract( + description, + _instanceSettings.ResolveMentionsInProfiles + ); description = extracted.content; - _statisticsHandler.ExtractedDescription(extracted.tags.Count(x => x.type == "Mention")); + _statisticsHandler.ExtractedDescription( + extracted.tags.Count(x => x.type == "Mention") + ); } var attachments = new List(); - attachments.Add(new UserAttachment - { - type = "PropertyValue", - name = _instanceSettings.TwitterDomainLabel != "" ? _instanceSettings.TwitterDomainLabel : _instanceSettings.TwitterDomain, - value = $"https://{_instanceSettings.TwitterDomain}/{acct}" - }); - - if(_instanceSettings.TwitterDomain != "twitter.com") - { - attachments.Add(new UserAttachment + attachments.Add( + new UserAttachment { type = "PropertyValue", - name = "Twitter", - value = $"twitter.com/{acct}" - }); + name = + _instanceSettings.TwitterDomainLabel != "" + ? _instanceSettings.TwitterDomainLabel + : _instanceSettings.TwitterDomain, + value = + $"https://{_instanceSettings.TwitterDomain}/{acct}" + } + ); + + if (_instanceSettings.TwitterDomain != "twitter.com") + { + attachments.Add( + new UserAttachment + { + type = "PropertyValue", + name = "Twitter", + value = $"twitter.com/{acct}" + } + ); } if (_instanceSettings.ShowAboutInstanceOnProfiles) { - attachments.Add(new UserAttachment - { - type = "PropertyValue", - name = $"About {_instanceSettings.Name}", - value = $"https://{_instanceSettings.Domain}/About" - }); + attachments.Add( + new UserAttachment + { + type = "PropertyValue", + name = $"About {_instanceSettings.Name}", + value = + $"https://{_instanceSettings.Domain}/About" + } + ); } var user = new Actor { id = actorUrl, - type = "Service", + type = "Service", followers = $"{actorUrl}/followers", preferredUsername = acct, name = twitterUser.Name, @@ -125,16 +170,8 @@ namespace BirdsiteLive.Domain owner = actorUrl, publicKeyPem = _cryptoService.GetUserPem(acct) }, - icon = new Image - { - mediaType = "image/jpeg", - url = twitterUser.ProfileImageUrl - }, - image = new Image - { - mediaType = "image/jpeg", - url = twitterUser.ProfileBannerURL - }, + icon = new Image { mediaType = "image/jpeg", url = twitterUser.ProfileImageUrl }, + image = new Image { mediaType = "image/jpeg", url = twitterUser.ProfileBannerURL }, attachment = attachments.ToArray(), endpoints = new EndPoints { @@ -165,49 +202,96 @@ namespace BirdsiteLive.Domain return user; } - public async Task FollowRequestedAsync(string signature, string method, string path, string queryString, Dictionary requestHeaders, ActivityFollow activity, string body) + public async Task FollowRequestedAsync( + string signature, + string method, + string path, + string queryString, + Dictionary requestHeaders, + ActivityFollow activity, + string body + ) { // Validate - var sigValidation = await ValidateSignature(activity.actor, signature, method, path, queryString, requestHeaders, body); - if (!sigValidation.SignatureIsValidated) return false; + var sigValidation = await ValidateSignature( + activity.actor, + signature, + method, + path, + queryString, + requestHeaders, + body + ); + if (!sigValidation.SignatureIsValidated) + return false; // Prepare data var followerUserName = sigValidation.User.preferredUsername.ToLowerInvariant().Trim(); - var followerHost = sigValidation.User.url.Replace("https://", string.Empty).Split('/').First(); + var followerHost = sigValidation.User.url + .Replace("https://", string.Empty) + .Split('/') + .First(); var followerInbox = sigValidation.User.inbox; var followerSharedInbox = sigValidation.User?.endpoints?.sharedInbox; - var twitterUser = activity.apObject.Split('/').Last().Replace("@", string.Empty).ToLowerInvariant().Trim(); + var twitterUser = activity.apObject + .Split('/') + .Last() + .Replace("@", string.Empty) + .ToLowerInvariant() + .Trim(); // Make sure to only keep routes followerInbox = OnlyKeepRoute(followerInbox, followerHost); followerSharedInbox = OnlyKeepRoute(followerSharedInbox, followerHost); - + // Validate Moderation status - var followerModPolicy = _moderationRepository.GetModerationType(ModerationEntityTypeEnum.Follower); + var followerModPolicy = _moderationRepository.GetModerationType( + ModerationEntityTypeEnum.Follower + ); if (followerModPolicy != ModerationTypeEnum.None) { - var followerStatus = _moderationRepository.CheckStatus(ModerationEntityTypeEnum.Follower, $"@{followerUserName}@{followerHost}"); - - if(followerModPolicy == ModerationTypeEnum.WhiteListing && followerStatus != ModeratedTypeEnum.WhiteListed || - followerModPolicy == ModerationTypeEnum.BlackListing && followerStatus == ModeratedTypeEnum.BlackListed) + var followerStatus = _moderationRepository.CheckStatus( + ModerationEntityTypeEnum.Follower, + $"@{followerUserName}@{followerHost}" + ); + + if ( + followerModPolicy == ModerationTypeEnum.WhiteListing + && followerStatus != ModeratedTypeEnum.WhiteListed + || followerModPolicy == ModerationTypeEnum.BlackListing + && followerStatus == ModeratedTypeEnum.BlackListed + ) return await SendRejectFollowAsync(activity, followerHost); } // Validate TwitterAccount status - var twitterAccountModPolicy = _moderationRepository.GetModerationType(ModerationEntityTypeEnum.TwitterAccount); + var twitterAccountModPolicy = _moderationRepository.GetModerationType( + ModerationEntityTypeEnum.TwitterAccount + ); if (twitterAccountModPolicy != ModerationTypeEnum.None) { - var twitterUserStatus = _moderationRepository.CheckStatus(ModerationEntityTypeEnum.TwitterAccount, twitterUser); - if (twitterAccountModPolicy == ModerationTypeEnum.WhiteListing && twitterUserStatus != ModeratedTypeEnum.WhiteListed || - twitterAccountModPolicy == ModerationTypeEnum.BlackListing && twitterUserStatus == ModeratedTypeEnum.BlackListed) + var twitterUserStatus = _moderationRepository.CheckStatus( + ModerationEntityTypeEnum.TwitterAccount, + twitterUser + ); + if ( + twitterAccountModPolicy == ModerationTypeEnum.WhiteListing + && twitterUserStatus != ModeratedTypeEnum.WhiteListed + || twitterAccountModPolicy == ModerationTypeEnum.BlackListing + && twitterUserStatus == ModeratedTypeEnum.BlackListed + ) return await SendRejectFollowAsync(activity, followerHost); } // Validate follower count < MaxFollowsPerUser - if (_instanceSettings.MaxFollowsPerUser > 0) { + if (_instanceSettings.MaxFollowsPerUser > 0) + { var follower = await _followerDal.GetFollowerAsync(followerUserName, followerHost); - if (follower != null && follower.Followings.Count + 1 > _instanceSettings.MaxFollowsPerUser) + if ( + follower != null + && follower.Followings.Count + 1 > _instanceSettings.MaxFollowsPerUser + ) { return await SendRejectFollowAsync(activity, followerHost); } @@ -218,7 +302,14 @@ namespace BirdsiteLive.Domain if (!user.Protected) { // Execute - await _processFollowUser.ExecuteAsync(followerUserName, followerHost, twitterUser, followerInbox, followerSharedInbox, activity.actor); + await _processFollowUser.ExecuteAsync( + followerUserName, + followerHost, + twitterUser, + followerInbox, + followerSharedInbox, + activity.actor + ); return await SendAcceptFollowAsync(activity, followerHost); } @@ -227,7 +318,7 @@ namespace BirdsiteLive.Domain return await SendRejectFollowAsync(activity, followerHost); } } - + private async Task SendAcceptFollowAsync(ActivityFollow activity, string followerHost) { var acceptFollow = new ActivityAcceptFollow() @@ -244,9 +335,12 @@ namespace BirdsiteLive.Domain apObject = activity.apObject } }; - var result = await _activityPubService.PostDataAsync(acceptFollow, followerHost, activity.apObject); - return result == HttpStatusCode.Accepted || - result == HttpStatusCode.OK; //TODO: revamp this for better error handling + var result = await _activityPubService.PostDataAsync( + acceptFollow, + followerHost, + activity.apObject + ); + return result == HttpStatusCode.Accepted || result == HttpStatusCode.OK; //TODO: revamp this for better error handling } public async Task SendRejectFollowAsync(ActivityFollow activity, string followerHost) @@ -265,14 +359,17 @@ namespace BirdsiteLive.Domain apObject = activity.apObject } }; - var result = await _activityPubService.PostDataAsync(acceptFollow, followerHost, activity.apObject); - return result == HttpStatusCode.Accepted || - result == HttpStatusCode.OK; //TODO: revamp this for better error handling + var result = await _activityPubService.PostDataAsync( + acceptFollow, + followerHost, + activity.apObject + ); + return result == HttpStatusCode.Accepted || result == HttpStatusCode.OK; //TODO: revamp this for better error handling } private string OnlyKeepRoute(string inbox, string host) { - if (string.IsNullOrWhiteSpace(inbox)) + if (string.IsNullOrWhiteSpace(inbox)) return null; if (inbox.Contains(host)) @@ -281,18 +378,40 @@ namespace BirdsiteLive.Domain return inbox; } - public async Task UndoFollowRequestedAsync(string signature, string method, string path, string queryString, - Dictionary requestHeaders, ActivityUndoFollow activity, string body) + public async Task UndoFollowRequestedAsync( + string signature, + string method, + string path, + string queryString, + Dictionary requestHeaders, + ActivityUndoFollow activity, + string body + ) { // Validate - var sigValidation = await ValidateSignature(activity.actor, signature, method, path, queryString, requestHeaders, body); - if (!sigValidation.SignatureIsValidated) return false; + var sigValidation = await ValidateSignature( + activity.actor, + signature, + method, + path, + queryString, + requestHeaders, + body + ); + if (!sigValidation.SignatureIsValidated) + return false; // Save Follow in DB var followerUserName = sigValidation.User.preferredUsername.ToLowerInvariant(); - var followerHost = sigValidation.User.url.Replace("https://", string.Empty).Split('/').First(); + var followerHost = sigValidation.User.url + .Replace("https://", string.Empty) + .Split('/') + .First(); //var followerInbox = sigValidation.User.inbox; - var twitterUser = activity.apObject.apObject.Split('/').Last().Replace("@", string.Empty); + var twitterUser = activity.apObject.apObject + .Split('/') + .Last() + .Replace("@", string.Empty); await _processUndoFollowUser.ExecuteAsync(followerUserName, followerHost, twitterUser); // Send Accept Activity @@ -310,24 +429,40 @@ namespace BirdsiteLive.Domain apObject = activity.apObject } }; - var result = await _activityPubService.PostDataAsync(acceptFollow, followerHost, activity.apObject.apObject); + var result = await _activityPubService.PostDataAsync( + acceptFollow, + followerHost, + activity.apObject.apObject + ); return result == HttpStatusCode.Accepted || result == HttpStatusCode.OK; //TODO: revamp this for better error handling } - private async Task ValidateSignature(string actor, string rawSig, string method, string path, string queryString, Dictionary requestHeaders, string body) + private async Task ValidateSignature( + string actor, + string rawSig, + string method, + string path, + string queryString, + Dictionary requestHeaders, + string body + ) { //Check Date Validity var date = requestHeaders["date"]; var d = DateTime.Parse(date).ToUniversalTime(); var now = DateTime.UtcNow; var delta = Math.Abs((d - now).TotalSeconds); - if (delta > 30) return new SignatureValidationResult { SignatureIsValidated = false }; - + if (delta > 30) + return new SignatureValidationResult { SignatureIsValidated = false }; + //Check Digest var digest = requestHeaders["digest"]; - var digestHash = digest.Split(new [] {"SHA-256="},StringSplitOptions.RemoveEmptyEntries).LastOrDefault(); + var digestHash = digest + .Split(new[] { "SHA-256=" }, StringSplitOptions.RemoveEmptyEntries) + .LastOrDefault(); var calculatedDigestHash = _cryptoService.ComputeSha256Hash(body); - if (digestHash != calculatedDigestHash) return new SignatureValidationResult { SignatureIsValidated = false }; + if (digestHash != calculatedDigestHash) + return new SignatureValidationResult { SignatureIsValidated = false }; //Check Signature var signatures = rawSig.Split(','); @@ -347,15 +482,19 @@ namespace BirdsiteLive.Domain var remoteUser = await _activityPubService.GetUser(actor); // Prepare Key data - var toDecode = remoteUser.publicKey.publicKeyPem.Trim().Remove(0, remoteUser.publicKey.publicKeyPem.IndexOf('\n')); + var toDecode = remoteUser.publicKey.publicKeyPem + .Trim() + .Remove(0, remoteUser.publicKey.publicKeyPem.IndexOf('\n')); toDecode = toDecode.Remove(toDecode.LastIndexOf('\n')).Replace("\n", ""); var signKey = ASN1.ToRSA(Convert.FromBase64String(toDecode)); var toSign = new StringBuilder(); foreach (var headerKey in headers.Split(' ')) { - if (headerKey == "(request-target)") toSign.Append($"(request-target): {method.ToLower()} {path}{queryString}\n"); - else toSign.Append($"{headerKey}: {string.Join(", ", requestHeaders[headerKey])}\n"); + if (headerKey == "(request-target)") + toSign.Append($"(request-target): {method.ToLower()} {path}{queryString}\n"); + else + toSign.Append($"{headerKey}: {string.Join(", ", requestHeaders[headerKey])}\n"); } toSign.Remove(toSign.Length - 1, 1); @@ -366,7 +505,12 @@ namespace BirdsiteLive.Domain key.ImportParameters(rsaKeyInfo); // Trust and Verify - var result = signKey.VerifyData(Encoding.UTF8.GetBytes(toSign.ToString()), sig, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); + var result = signKey.VerifyData( + Encoding.UTF8.GetBytes(toSign.ToString()), + sig, + HashAlgorithmName.SHA256, + RSASignaturePadding.Pkcs1 + ); return new SignatureValidationResult() { @@ -376,7 +520,7 @@ namespace BirdsiteLive.Domain } } - public class SignatureValidationResult + public class SignatureValidationResult { public bool SignatureIsValidated { get; set; } public Actor User { get; set; } diff --git a/src/BirdsiteLive.Moderation/Actions/RejectAllFollowingsAction.cs b/src/BirdsiteLive.Moderation/Actions/RejectAllFollowingsAction.cs index 9a1b1bc..e9f3f93 100644 --- a/src/BirdsiteLive.Moderation/Actions/RejectAllFollowingsAction.cs +++ b/src/BirdsiteLive.Moderation/Actions/RejectAllFollowingsAction.cs @@ -1,5 +1,6 @@ -using System; +using System; using System.Threading.Tasks; + using BirdsiteLive.ActivityPub; using BirdsiteLive.ActivityPub.Converters; using BirdsiteLive.Common.Settings; @@ -21,7 +22,11 @@ namespace BirdsiteLive.Moderation.Actions private readonly InstanceSettings _instanceSettings; #region Ctor - public RejectAllFollowingsAction(ITwitterUserDal twitterUserDal, IUserService userService, InstanceSettings instanceSettings) + public RejectAllFollowingsAction( + ITwitterUserDal twitterUserDal, + IUserService userService, + InstanceSettings instanceSettings + ) { _twitterUserDal = twitterUserDal; _userService = userService; @@ -49,4 +54,4 @@ namespace BirdsiteLive.Moderation.Actions } } } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive.Moderation/Actions/RejectFollowingAction.cs b/src/BirdsiteLive.Moderation/Actions/RejectFollowingAction.cs index c5963eb..87c5713 100644 --- a/src/BirdsiteLive.Moderation/Actions/RejectFollowingAction.cs +++ b/src/BirdsiteLive.Moderation/Actions/RejectFollowingAction.cs @@ -1,5 +1,6 @@ -using System; +using System; using System.Threading.Tasks; + using BirdsiteLive.ActivityPub; using BirdsiteLive.ActivityPub.Converters; using BirdsiteLive.Common.Settings; @@ -17,7 +18,7 @@ namespace BirdsiteLive.Moderation.Actions { private readonly IUserService _userService; private readonly InstanceSettings _instanceSettings; - + #region Ctor public RejectFollowingAction(IUserService userService, InstanceSettings instanceSettings) { @@ -41,4 +42,4 @@ namespace BirdsiteLive.Moderation.Actions catch (Exception) { } } } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive.Moderation/Actions/RemoveFollowerAction.cs b/src/BirdsiteLive.Moderation/Actions/RemoveFollowerAction.cs index 8ab3132..b56cb95 100644 --- a/src/BirdsiteLive.Moderation/Actions/RemoveFollowerAction.cs +++ b/src/BirdsiteLive.Moderation/Actions/RemoveFollowerAction.cs @@ -1,6 +1,7 @@ -using System; +using System; using System.Linq; using System.Threading.Tasks; + using BirdsiteLive.ActivityPub; using BirdsiteLive.ActivityPub.Converters; using BirdsiteLive.Common.Settings; @@ -22,7 +23,11 @@ namespace BirdsiteLive.Moderation.Actions private readonly IRejectAllFollowingsAction _rejectAllFollowingsAction; #region Ctor - public RemoveFollowerAction(IFollowersDal followersDal, ITwitterUserDal twitterUserDal, IRejectAllFollowingsAction rejectAllFollowingsAction) + public RemoveFollowerAction( + IFollowersDal followersDal, + ITwitterUserDal twitterUserDal, + IRejectAllFollowingsAction rejectAllFollowingsAction + ) { _followersDal = followersDal; _twitterUserDal = twitterUserDal; @@ -48,4 +53,4 @@ namespace BirdsiteLive.Moderation.Actions await _followersDal.DeleteFollowerAsync(follower.Id); } } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive.Moderation/Actions/RemoveTwitterAccountAction.cs b/src/BirdsiteLive.Moderation/Actions/RemoveTwitterAccountAction.cs index 714cca6..87e9c57 100644 --- a/src/BirdsiteLive.Moderation/Actions/RemoveTwitterAccountAction.cs +++ b/src/BirdsiteLive.Moderation/Actions/RemoveTwitterAccountAction.cs @@ -1,5 +1,6 @@ -using System.Linq; +using System.Linq; using System.Threading.Tasks; + using BirdsiteLive.DAL.Contracts; using BirdsiteLive.DAL.Models; @@ -17,7 +18,11 @@ namespace BirdsiteLive.Moderation.Actions private readonly IRejectFollowingAction _rejectFollowingAction; #region Ctor - public RemoveTwitterAccountAction(IFollowersDal followersDal, ITwitterUserDal twitterUserDal, IRejectFollowingAction rejectFollowingAction) + public RemoveTwitterAccountAction( + IFollowersDal followersDal, + ITwitterUserDal twitterUserDal, + IRejectFollowingAction rejectFollowingAction + ) { _followersDal = followersDal; _twitterUserDal = twitterUserDal; @@ -27,12 +32,12 @@ namespace BirdsiteLive.Moderation.Actions public async Task ProcessAsync(SyncTwitterUser twitterUser) { - // Check Followers + // Check Followers var twitterUserId = twitterUser.Id; var followers = await _followersDal.GetFollowersAsync(twitterUserId); - + // Remove all Followers - foreach (var follower in followers) + foreach (var follower in followers) { // Perform undo following to user instance await _rejectFollowingAction.ProcessAsync(follower, twitterUser); @@ -54,4 +59,4 @@ namespace BirdsiteLive.Moderation.Actions await _twitterUserDal.DeleteTwitterUserAsync(twitterUserId); } } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive.Moderation/BirdsiteLive.Moderation.csproj b/src/BirdsiteLive.Moderation/BirdsiteLive.Moderation.csproj index b7bbeea..0dfa367 100644 --- a/src/BirdsiteLive.Moderation/BirdsiteLive.Moderation.csproj +++ b/src/BirdsiteLive.Moderation/BirdsiteLive.Moderation.csproj @@ -1,7 +1,7 @@ - netstandard2.0 + net6.0 diff --git a/src/BirdsiteLive.Moderation/ModerationPipeline.cs b/src/BirdsiteLive.Moderation/ModerationPipeline.cs index bc92a17..d3a0aa8 100644 --- a/src/BirdsiteLive.Moderation/ModerationPipeline.cs +++ b/src/BirdsiteLive.Moderation/ModerationPipeline.cs @@ -1,7 +1,9 @@ -using System; +using System; using System.Threading.Tasks; + using BirdsiteLive.Domain.Repository; using BirdsiteLive.Moderation.Processors; + using Microsoft.Extensions.Logging; namespace BirdsiteLive.Moderation @@ -20,7 +22,12 @@ namespace BirdsiteLive.Moderation private readonly ILogger _logger; #region Ctor - public ModerationPipeline(IModerationRepository moderationRepository, IFollowerModerationProcessor followerModerationProcessor, ITwitterAccountModerationProcessor twitterAccountModerationProcessor, ILogger logger) + public ModerationPipeline( + IModerationRepository moderationRepository, + IFollowerModerationProcessor followerModerationProcessor, + ITwitterAccountModerationProcessor twitterAccountModerationProcessor, + ILogger logger + ) { _moderationRepository = moderationRepository; _followerModerationProcessor = followerModerationProcessor; @@ -44,16 +51,22 @@ namespace BirdsiteLive.Moderation private async Task CheckFollowerModerationPolicyAsync() { - var followerPolicy = _moderationRepository.GetModerationType(ModerationEntityTypeEnum.Follower); - if (followerPolicy == ModerationTypeEnum.None) return; + var followerPolicy = _moderationRepository.GetModerationType( + ModerationEntityTypeEnum.Follower + ); + if (followerPolicy == ModerationTypeEnum.None) + return; await _followerModerationProcessor.ProcessAsync(followerPolicy); } private async Task CheckTwitterAccountModerationPolicyAsync() { - var twitterAccountPolicy = _moderationRepository.GetModerationType(ModerationEntityTypeEnum.TwitterAccount); - if (twitterAccountPolicy == ModerationTypeEnum.None) return; + var twitterAccountPolicy = _moderationRepository.GetModerationType( + ModerationEntityTypeEnum.TwitterAccount + ); + if (twitterAccountPolicy == ModerationTypeEnum.None) + return; await _twitterAccountModerationProcessor.ProcessAsync(twitterAccountPolicy); } diff --git a/src/BirdsiteLive.Moderation/Processors/FollowerModerationProcessor.cs b/src/BirdsiteLive.Moderation/Processors/FollowerModerationProcessor.cs index d697351..df8aaac 100644 --- a/src/BirdsiteLive.Moderation/Processors/FollowerModerationProcessor.cs +++ b/src/BirdsiteLive.Moderation/Processors/FollowerModerationProcessor.cs @@ -1,5 +1,6 @@ -using System; +using System; using System.Threading.Tasks; + using BirdsiteLive.DAL.Contracts; using BirdsiteLive.Domain.Repository; using BirdsiteLive.Moderation.Actions; @@ -18,7 +19,11 @@ namespace BirdsiteLive.Moderation.Processors private readonly IRemoveFollowerAction _removeFollowerAction; #region Ctor - public FollowerModerationProcessor(IFollowersDal followersDal, IModerationRepository moderationRepository, IRemoveFollowerAction removeFollowerAction) + public FollowerModerationProcessor( + IFollowersDal followersDal, + IModerationRepository moderationRepository, + IRemoveFollowerAction removeFollowerAction + ) { _followersDal = followersDal; _moderationRepository = moderationRepository; @@ -28,17 +33,26 @@ namespace BirdsiteLive.Moderation.Processors public async Task ProcessAsync(ModerationTypeEnum type) { - if (type == ModerationTypeEnum.None) return; + if (type == ModerationTypeEnum.None) + return; var followers = await _followersDal.GetAllFollowersAsync(); foreach (var follower in followers) { - var followerHandle = $"@{follower.Acct.Trim()}@{follower.Host.Trim()}".ToLowerInvariant(); - var status = _moderationRepository.CheckStatus(ModerationEntityTypeEnum.Follower, followerHandle); + var followerHandle = + $"@{follower.Acct.Trim()}@{follower.Host.Trim()}".ToLowerInvariant(); + var status = _moderationRepository.CheckStatus( + ModerationEntityTypeEnum.Follower, + followerHandle + ); - if (type == ModerationTypeEnum.WhiteListing && status != ModeratedTypeEnum.WhiteListed || - type == ModerationTypeEnum.BlackListing && status == ModeratedTypeEnum.BlackListed) + if ( + type == ModerationTypeEnum.WhiteListing + && status != ModeratedTypeEnum.WhiteListed + || type == ModerationTypeEnum.BlackListing + && status == ModeratedTypeEnum.BlackListed + ) { Console.WriteLine($"Remove {followerHandle}"); await _removeFollowerAction.ProcessAsync(follower); @@ -46,4 +60,4 @@ namespace BirdsiteLive.Moderation.Processors } } } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive.Moderation/Processors/TwitterAccountModerationProcessor.cs b/src/BirdsiteLive.Moderation/Processors/TwitterAccountModerationProcessor.cs index 91e3931..b2785d4 100644 --- a/src/BirdsiteLive.Moderation/Processors/TwitterAccountModerationProcessor.cs +++ b/src/BirdsiteLive.Moderation/Processors/TwitterAccountModerationProcessor.cs @@ -1,4 +1,5 @@ -using System.Threading.Tasks; +using System.Threading.Tasks; + using BirdsiteLive.DAL.Contracts; using BirdsiteLive.Domain.Repository; using BirdsiteLive.Moderation.Actions; @@ -15,9 +16,13 @@ namespace BirdsiteLive.Moderation.Processors private readonly ITwitterUserDal _twitterUserDal; private readonly IModerationRepository _moderationRepository; private readonly IRemoveTwitterAccountAction _removeTwitterAccountAction; - + #region Ctor - public TwitterAccountModerationProcessor(ITwitterUserDal twitterUserDal, IModerationRepository moderationRepository, IRemoveTwitterAccountAction removeTwitterAccountAction) + public TwitterAccountModerationProcessor( + ITwitterUserDal twitterUserDal, + IModerationRepository moderationRepository, + IRemoveTwitterAccountAction removeTwitterAccountAction + ) { _twitterUserDal = twitterUserDal; _moderationRepository = moderationRepository; @@ -27,19 +32,27 @@ namespace BirdsiteLive.Moderation.Processors public async Task ProcessAsync(ModerationTypeEnum type) { - if (type == ModerationTypeEnum.None) return; - + if (type == ModerationTypeEnum.None) + return; + var twitterUsers = await _twitterUserDal.GetAllTwitterUsersAsync(); foreach (var user in twitterUsers) { var userHandle = user.Acct.ToLowerInvariant().Trim(); - var status = _moderationRepository.CheckStatus(ModerationEntityTypeEnum.TwitterAccount, userHandle); + var status = _moderationRepository.CheckStatus( + ModerationEntityTypeEnum.TwitterAccount, + userHandle + ); - if (type == ModerationTypeEnum.WhiteListing && status != ModeratedTypeEnum.WhiteListed || - type == ModerationTypeEnum.BlackListing && status == ModeratedTypeEnum.BlackListed) + if ( + type == ModerationTypeEnum.WhiteListing + && status != ModeratedTypeEnum.WhiteListed + || type == ModerationTypeEnum.BlackListing + && status == ModeratedTypeEnum.BlackListed + ) await _removeTwitterAccountAction.ProcessAsync(user); } } } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive.Pipeline/BirdsiteLive.Pipeline.csproj b/src/BirdsiteLive.Pipeline/BirdsiteLive.Pipeline.csproj index 8601b19..d576ce7 100644 --- a/src/BirdsiteLive.Pipeline/BirdsiteLive.Pipeline.csproj +++ b/src/BirdsiteLive.Pipeline/BirdsiteLive.Pipeline.csproj @@ -1,7 +1,7 @@ - + - netstandard2.0 + net6.0 latest diff --git a/src/BirdsiteLive.Pipeline/Contracts/IRefreshTwitterUserStatusProcessor.cs b/src/BirdsiteLive.Pipeline/Contracts/IRefreshTwitterUserStatusProcessor.cs index 9f20e59..8ec1d2b 100644 --- a/src/BirdsiteLive.Pipeline/Contracts/IRefreshTwitterUserStatusProcessor.cs +++ b/src/BirdsiteLive.Pipeline/Contracts/IRefreshTwitterUserStatusProcessor.cs @@ -1,5 +1,6 @@ -using System.Threading; +using System.Threading; using System.Threading.Tasks; + using BirdsiteLive.DAL.Models; using BirdsiteLive.Pipeline.Models; @@ -7,6 +8,9 @@ namespace BirdsiteLive.Pipeline.Contracts { public interface IRefreshTwitterUserStatusProcessor { - Task ProcessAsync(SyncTwitterUser[] syncTwitterUsers, CancellationToken ct); + Task ProcessAsync( + SyncTwitterUser[] syncTwitterUsers, + CancellationToken ct + ); } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive.Pipeline/Contracts/IRetrieveFollowersProcessor.cs b/src/BirdsiteLive.Pipeline/Contracts/IRetrieveFollowersProcessor.cs index a9ef35c..e7c8707 100644 --- a/src/BirdsiteLive.Pipeline/Contracts/IRetrieveFollowersProcessor.cs +++ b/src/BirdsiteLive.Pipeline/Contracts/IRetrieveFollowersProcessor.cs @@ -1,13 +1,17 @@ -using System.Collections.Generic; +using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; + using BirdsiteLive.Pipeline.Models; namespace BirdsiteLive.Pipeline.Contracts { public interface IRetrieveFollowersProcessor { - Task> ProcessAsync(UserWithDataToSync[] userWithTweetsToSyncs, CancellationToken ct); + Task> ProcessAsync( + UserWithDataToSync[] userWithTweetsToSyncs, + CancellationToken ct + ); //IAsyncEnumerable ProcessAsync(UserWithTweetsToSync[] userWithTweetsToSyncs, CancellationToken ct); } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive.Pipeline/Contracts/IRetrieveTweetsProcessor.cs b/src/BirdsiteLive.Pipeline/Contracts/IRetrieveTweetsProcessor.cs index 49712c2..9d56094 100644 --- a/src/BirdsiteLive.Pipeline/Contracts/IRetrieveTweetsProcessor.cs +++ b/src/BirdsiteLive.Pipeline/Contracts/IRetrieveTweetsProcessor.cs @@ -1,5 +1,6 @@ -using System.Threading; +using System.Threading; using System.Threading.Tasks; + using BirdsiteLive.DAL.Models; using BirdsiteLive.Pipeline.Models; @@ -7,6 +8,9 @@ namespace BirdsiteLive.Pipeline.Contracts { public interface IRetrieveTweetsProcessor { - Task ProcessAsync(UserWithDataToSync[] syncTwitterUsers, CancellationToken ct); + Task ProcessAsync( + UserWithDataToSync[] syncTwitterUsers, + CancellationToken ct + ); } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive.Pipeline/Contracts/IRetrieveTwitterUsersProcessor.cs b/src/BirdsiteLive.Pipeline/Contracts/IRetrieveTwitterUsersProcessor.cs index b71ae93..f771ee8 100644 --- a/src/BirdsiteLive.Pipeline/Contracts/IRetrieveTwitterUsersProcessor.cs +++ b/src/BirdsiteLive.Pipeline/Contracts/IRetrieveTwitterUsersProcessor.cs @@ -1,12 +1,16 @@ -using System.Threading; +using System.Threading; using System.Threading.Tasks; using System.Threading.Tasks.Dataflow; + using BirdsiteLive.DAL.Models; namespace BirdsiteLive.Pipeline.Contracts { public interface IRetrieveTwitterUsersProcessor { - Task GetTwitterUsersAsync(BufferBlock twitterUsersBufferBlock, CancellationToken ct); + Task GetTwitterUsersAsync( + BufferBlock twitterUsersBufferBlock, + CancellationToken ct + ); } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive.Pipeline/Contracts/ISaveProgressionProcessor.cs b/src/BirdsiteLive.Pipeline/Contracts/ISaveProgressionProcessor.cs index 6b1c9ba..5d76b05 100644 --- a/src/BirdsiteLive.Pipeline/Contracts/ISaveProgressionProcessor.cs +++ b/src/BirdsiteLive.Pipeline/Contracts/ISaveProgressionProcessor.cs @@ -1,5 +1,6 @@ -using System.Threading; +using System.Threading; using System.Threading.Tasks; + using BirdsiteLive.Pipeline.Models; namespace BirdsiteLive.Pipeline.Contracts @@ -8,4 +9,4 @@ namespace BirdsiteLive.Pipeline.Contracts { Task ProcessAsync(UserWithDataToSync userWithTweetsToSync, CancellationToken ct); } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive.Pipeline/Contracts/ISendTweetsToFollowersProcessor.cs b/src/BirdsiteLive.Pipeline/Contracts/ISendTweetsToFollowersProcessor.cs index 33db423..9334ff0 100644 --- a/src/BirdsiteLive.Pipeline/Contracts/ISendTweetsToFollowersProcessor.cs +++ b/src/BirdsiteLive.Pipeline/Contracts/ISendTweetsToFollowersProcessor.cs @@ -1,11 +1,15 @@ -using System.Threading; +using System.Threading; using System.Threading.Tasks; + using BirdsiteLive.Pipeline.Models; namespace BirdsiteLive.Pipeline.Contracts { public interface ISendTweetsToFollowersProcessor { - Task ProcessAsync(UserWithDataToSync userWithTweetsToSync, CancellationToken ct); + Task ProcessAsync( + UserWithDataToSync userWithTweetsToSync, + CancellationToken ct + ); } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive.Pipeline/Models/UserWithDataToSync.cs b/src/BirdsiteLive.Pipeline/Models/UserWithDataToSync.cs index c5e6639..4af24e2 100644 --- a/src/BirdsiteLive.Pipeline/Models/UserWithDataToSync.cs +++ b/src/BirdsiteLive.Pipeline/Models/UserWithDataToSync.cs @@ -1,5 +1,6 @@ -using BirdsiteLive.DAL.Models; +using BirdsiteLive.DAL.Models; using BirdsiteLive.Twitter.Models; + using Tweetinvi.Models; namespace BirdsiteLive.Pipeline.Models @@ -10,4 +11,4 @@ namespace BirdsiteLive.Pipeline.Models public ExtractedTweet[] Tweets { get; set; } public Follower[] Followers { get; set; } } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive.Pipeline/Processors/RefreshTwitterUserStatusProcessor.cs b/src/BirdsiteLive.Pipeline/Processors/RefreshTwitterUserStatusProcessor.cs index 3a36be3..d54d30b 100644 --- a/src/BirdsiteLive.Pipeline/Processors/RefreshTwitterUserStatusProcessor.cs +++ b/src/BirdsiteLive.Pipeline/Processors/RefreshTwitterUserStatusProcessor.cs @@ -1,7 +1,8 @@ -using System; +using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; + using BirdsiteLive.Common.Settings; using BirdsiteLive.DAL.Contracts; using BirdsiteLive.DAL.Models; @@ -20,7 +21,12 @@ namespace BirdsiteLive.Pipeline.Processors private readonly InstanceSettings _instanceSettings; #region Ctor - public RefreshTwitterUserStatusProcessor(ICachedTwitterUserService twitterUserService, ITwitterUserDal twitterUserDal, IRemoveTwitterAccountAction removeTwitterAccountAction, InstanceSettings instanceSettings) + public RefreshTwitterUserStatusProcessor( + ICachedTwitterUserService twitterUserService, + ITwitterUserDal twitterUserDal, + IRemoveTwitterAccountAction removeTwitterAccountAction, + InstanceSettings instanceSettings + ) { _twitterUserService = twitterUserService; _twitterUserDal = twitterUserDal; @@ -29,7 +35,10 @@ namespace BirdsiteLive.Pipeline.Processors } #endregion - public async Task ProcessAsync(SyncTwitterUser[] syncTwitterUsers, CancellationToken ct) + public async Task ProcessAsync( + SyncTwitterUser[] syncTwitterUsers, + CancellationToken ct + ) { var usersWtData = new List(); @@ -43,10 +52,7 @@ namespace BirdsiteLive.Pipeline.Processors else if (!userView.Protected) { user.FetchingErrorCount = 0; - var userWtData = new UserWithDataToSync - { - User = user - }; + var userWtData = new UserWithDataToSync { User = user }; usersWtData.Add(userWtData); } } @@ -73,4 +79,4 @@ namespace BirdsiteLive.Pipeline.Processors _twitterUserService.PurgeUser(user.Acct); } } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive.Pipeline/Processors/RetrieveFollowersProcessor.cs b/src/BirdsiteLive.Pipeline/Processors/RetrieveFollowersProcessor.cs index 57e3e49..da5077a 100644 --- a/src/BirdsiteLive.Pipeline/Processors/RetrieveFollowersProcessor.cs +++ b/src/BirdsiteLive.Pipeline/Processors/RetrieveFollowersProcessor.cs @@ -1,6 +1,7 @@ -using System.Collections.Generic; +using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; + using BirdsiteLive.DAL.Contracts; using BirdsiteLive.Pipeline.Contracts; using BirdsiteLive.Pipeline.Models; @@ -18,7 +19,10 @@ namespace BirdsiteLive.Pipeline.Processors } #endregion - public async Task> ProcessAsync(UserWithDataToSync[] userWithTweetsToSyncs, CancellationToken ct) + public async Task> ProcessAsync( + UserWithDataToSync[] userWithTweetsToSyncs, + CancellationToken ct + ) { //TODO multithread this foreach (var user in userWithTweetsToSyncs) @@ -30,4 +34,4 @@ namespace BirdsiteLive.Pipeline.Processors return userWithTweetsToSyncs; } } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive.Pipeline/Processors/RetrieveTweetsProcessor.cs b/src/BirdsiteLive.Pipeline/Processors/RetrieveTweetsProcessor.cs index 58d35d0..24c1899 100644 --- a/src/BirdsiteLive.Pipeline/Processors/RetrieveTweetsProcessor.cs +++ b/src/BirdsiteLive.Pipeline/Processors/RetrieveTweetsProcessor.cs @@ -1,15 +1,18 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; + using BirdsiteLive.DAL.Contracts; using BirdsiteLive.DAL.Models; using BirdsiteLive.Pipeline.Contracts; using BirdsiteLive.Pipeline.Models; using BirdsiteLive.Twitter; using BirdsiteLive.Twitter.Models; + using Microsoft.Extensions.Logging; + using Tweetinvi.Models; namespace BirdsiteLive.Pipeline.Processors @@ -22,7 +25,12 @@ namespace BirdsiteLive.Pipeline.Processors private readonly ILogger _logger; #region Ctor - public RetrieveTweetsProcessor(ITwitterTweetsService twitterTweetsService, ITwitterUserDal twitterUserDal, ICachedTwitterUserService twitterUserService, ILogger logger) + public RetrieveTweetsProcessor( + ITwitterTweetsService twitterTweetsService, + ITwitterUserDal twitterUserDal, + ICachedTwitterUserService twitterUserService, + ILogger logger + ) { _twitterTweetsService = twitterTweetsService; _twitterUserDal = twitterUserDal; @@ -31,7 +39,10 @@ namespace BirdsiteLive.Pipeline.Processors } #endregion - public async Task ProcessAsync(UserWithDataToSync[] syncTwitterUsers, CancellationToken ct) + public async Task ProcessAsync( + UserWithDataToSync[] syncTwitterUsers, + CancellationToken ct + ) { var usersWtTweets = new List(); @@ -49,12 +60,24 @@ namespace BirdsiteLive.Pipeline.Processors { var tweetId = tweets.Last().Id; var now = DateTime.UtcNow; - await _twitterUserDal.UpdateTwitterUserAsync(user.Id, tweetId, tweetId, user.FetchingErrorCount, now); + await _twitterUserDal.UpdateTwitterUserAsync( + user.Id, + tweetId, + tweetId, + user.FetchingErrorCount, + now + ); } else { var now = DateTime.UtcNow; - await _twitterUserDal.UpdateTwitterUserAsync(user.Id, user.LastTweetPostedId, user.LastTweetSynchronizedForAllFollowersId, user.FetchingErrorCount, now); + await _twitterUserDal.UpdateTwitterUserAsync( + user.Id, + user.LastTweetPostedId, + user.LastTweetSynchronizedForAllFollowersId, + user.FetchingErrorCount, + now + ); } } @@ -64,21 +87,30 @@ namespace BirdsiteLive.Pipeline.Processors private ExtractedTweet[] RetrieveNewTweets(SyncTwitterUser user) { var tweets = new ExtractedTweet[0]; - + try { if (user.LastTweetPostedId == -1) tweets = _twitterTweetsService.GetTimeline(user.Acct, 1); else - tweets = _twitterTweetsService.GetTimeline(user.Acct, 200, user.LastTweetSynchronizedForAllFollowersId); + tweets = _twitterTweetsService.GetTimeline( + user.Acct, + 200, + user.LastTweetSynchronizedForAllFollowersId + ); } catch (Exception e) { - _logger.LogError(e, "Error retrieving TL of {Username} from {LastTweetPostedId}, purging user from cache", user.Acct, user.LastTweetPostedId); + _logger.LogError( + e, + "Error retrieving TL of {Username} from {LastTweetPostedId}, purging user from cache", + user.Acct, + user.LastTweetPostedId + ); _twitterUserService.PurgeUser(user.Acct); } return tweets; } } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive.Pipeline/Processors/RetrieveTwitterUsersProcessor.cs b/src/BirdsiteLive.Pipeline/Processors/RetrieveTwitterUsersProcessor.cs index 973b672..1b07cde 100644 --- a/src/BirdsiteLive.Pipeline/Processors/RetrieveTwitterUsersProcessor.cs +++ b/src/BirdsiteLive.Pipeline/Processors/RetrieveTwitterUsersProcessor.cs @@ -1,14 +1,16 @@ -using System; +using System; using System.Linq; using System.Threading; using System.Threading.Tasks; using System.Threading.Tasks.Dataflow; + using BirdsiteLive.Common.Extensions; using BirdsiteLive.Common.Settings; using BirdsiteLive.DAL.Contracts; using BirdsiteLive.DAL.Models; using BirdsiteLive.Pipeline.Contracts; using BirdsiteLive.Pipeline.Tools; + using Microsoft.Extensions.Logging; namespace BirdsiteLive.Pipeline.Processors @@ -18,11 +20,14 @@ namespace BirdsiteLive.Pipeline.Processors private readonly ITwitterUserDal _twitterUserDal; private readonly IMaxUsersNumberProvider _maxUsersNumberProvider; private readonly ILogger _logger; - - public int WaitFactor = 1000 * 60; //1 min + public int WaitFactor = 1000 * 60; //1 min #region Ctor - public RetrieveTwitterUsersProcessor(ITwitterUserDal twitterUserDal, IMaxUsersNumberProvider maxUsersNumberProvider, ILogger logger) + public RetrieveTwitterUsersProcessor( + ITwitterUserDal twitterUserDal, + IMaxUsersNumberProvider maxUsersNumberProvider, + ILogger logger + ) { _twitterUserDal = twitterUserDal; _maxUsersNumberProvider = maxUsersNumberProvider; @@ -30,7 +35,10 @@ namespace BirdsiteLive.Pipeline.Processors } #endregion - public async Task GetTwitterUsersAsync(BufferBlock twitterUsersBufferBlock, CancellationToken ct) + public async Task GetTwitterUsersAsync( + BufferBlock twitterUsersBufferBlock, + CancellationToken ct + ) { for (; ; ) { @@ -42,7 +50,7 @@ namespace BirdsiteLive.Pipeline.Processors var users = await _twitterUserDal.GetAllTwitterUsersAsync(maxUsersNumber); var userCount = users.Any() ? users.Length : 1; - var splitNumber = (int) Math.Ceiling(userCount / 15d); + var splitNumber = (int)Math.Ceiling(userCount / 15d); var splitUsers = users.Split(splitNumber).ToList(); foreach (var u in splitUsers) @@ -55,7 +63,8 @@ namespace BirdsiteLive.Pipeline.Processors } var splitCount = splitUsers.Count(); - if (splitCount < 15) await Task.Delay((15 - splitCount) * WaitFactor, ct); //Always wait 15min + if (splitCount < 15) + await Task.Delay((15 - splitCount) * WaitFactor, ct); //Always wait 15min //// Extra wait time to fit 100.000/day limit //var extraWaitTime = (int)Math.Ceiling((60 / ((100000d / 24) / userCount)) - 15); @@ -69,4 +78,4 @@ namespace BirdsiteLive.Pipeline.Processors } } } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive.Pipeline/Processors/SaveProgressionProcessor.cs b/src/BirdsiteLive.Pipeline/Processors/SaveProgressionProcessor.cs index 1437255..d8e1909 100644 --- a/src/BirdsiteLive.Pipeline/Processors/SaveProgressionProcessor.cs +++ b/src/BirdsiteLive.Pipeline/Processors/SaveProgressionProcessor.cs @@ -1,10 +1,12 @@ -using System; +using System; using System.Linq; using System.Threading; using System.Threading.Tasks; + using BirdsiteLive.DAL.Contracts; using BirdsiteLive.Pipeline.Contracts; using BirdsiteLive.Pipeline.Models; + using Microsoft.Extensions.Logging; namespace BirdsiteLive.Pipeline.Processors @@ -15,14 +17,20 @@ namespace BirdsiteLive.Pipeline.Processors private readonly ILogger _logger; #region Ctor - public SaveProgressionProcessor(ITwitterUserDal twitterUserDal, ILogger logger) + public SaveProgressionProcessor( + ITwitterUserDal twitterUserDal, + ILogger logger + ) { _twitterUserDal = twitterUserDal; _logger = logger; } #endregion - public async Task ProcessAsync(UserWithDataToSync userWithTweetsToSync, CancellationToken ct) + public async Task ProcessAsync( + UserWithDataToSync userWithTweetsToSync, + CancellationToken ct + ) { try { @@ -31,25 +39,40 @@ namespace BirdsiteLive.Pipeline.Processors _logger.LogWarning("No tweets synchronized"); return; } - if(userWithTweetsToSync.Followers.Length == 0) + if (userWithTweetsToSync.Followers.Length == 0) { - _logger.LogWarning("No Followers found for {User}", userWithTweetsToSync.User.Acct); + _logger.LogWarning( + "No Followers found for {User}", + userWithTweetsToSync.User.Acct + ); return; } - + var userId = userWithTweetsToSync.User.Id; - var followingSyncStatuses = userWithTweetsToSync.Followers.Select(x => x.FollowingsSyncStatus[userId]).ToList(); - + var followingSyncStatuses = userWithTweetsToSync.Followers + .Select(x => x.FollowingsSyncStatus[userId]) + .ToList(); + if (followingSyncStatuses.Count == 0) { - _logger.LogWarning("No Followers sync found for {User}, Id: {UserId}", userWithTweetsToSync.User.Acct, userId); + _logger.LogWarning( + "No Followers sync found for {User}, Id: {UserId}", + userWithTweetsToSync.User.Acct, + userId + ); return; } var lastPostedTweet = userWithTweetsToSync.Tweets.Select(x => x.Id).Max(); var minimumSync = followingSyncStatuses.Min(); var now = DateTime.UtcNow; - await _twitterUserDal.UpdateTwitterUserAsync(userId, lastPostedTweet, minimumSync, userWithTweetsToSync.User.FetchingErrorCount, now); + await _twitterUserDal.UpdateTwitterUserAsync( + userId, + lastPostedTweet, + minimumSync, + userWithTweetsToSync.User.FetchingErrorCount, + now + ); } catch (Exception e) { @@ -58,4 +81,4 @@ namespace BirdsiteLive.Pipeline.Processors } } } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive.Pipeline/Processors/SendTweetsToFollowersProcessor.cs b/src/BirdsiteLive.Pipeline/Processors/SendTweetsToFollowersProcessor.cs index 65f9610..4973d0f 100644 --- a/src/BirdsiteLive.Pipeline/Processors/SendTweetsToFollowersProcessor.cs +++ b/src/BirdsiteLive.Pipeline/Processors/SendTweetsToFollowersProcessor.cs @@ -1,10 +1,11 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Threading; using System.Threading.Tasks; using System.Xml; + using BirdsiteLive.DAL.Contracts; using BirdsiteLive.DAL.Models; using BirdsiteLive.Domain; @@ -13,7 +14,9 @@ using BirdsiteLive.Pipeline.Models; using BirdsiteLive.Pipeline.Processors.SubTasks; using BirdsiteLive.Twitter; using BirdsiteLive.Twitter.Models; + using Microsoft.Extensions.Logging; + using Tweetinvi.Models; namespace BirdsiteLive.Pipeline.Processors @@ -26,7 +29,12 @@ namespace BirdsiteLive.Pipeline.Processors private readonly ILogger _logger; #region Ctor - public SendTweetsToFollowersProcessor(ISendTweetsToInboxTask sendTweetsToInboxTask, ISendTweetsToSharedInboxTask sendTweetsToSharedInbox, IFollowersDal followersDal, ILogger logger) + public SendTweetsToFollowersProcessor( + ISendTweetsToInboxTask sendTweetsToInboxTask, + ISendTweetsToSharedInboxTask sendTweetsToSharedInbox, + IFollowersDal followersDal, + ILogger logger + ) { _sendTweetsToInboxTask = sendTweetsToInboxTask; _sendTweetsToSharedInbox = sendTweetsToSharedInbox; @@ -35,7 +43,10 @@ namespace BirdsiteLive.Pipeline.Processors } #endregion - public async Task ProcessAsync(UserWithDataToSync userWithTweetsToSync, CancellationToken ct) + public async Task ProcessAsync( + UserWithDataToSync userWithTweetsToSync, + CancellationToken ct + ) { var user = userWithTweetsToSync.User; @@ -43,18 +54,30 @@ namespace BirdsiteLive.Pipeline.Processors var followersWtSharedInbox = userWithTweetsToSync.Followers .Where(x => !string.IsNullOrWhiteSpace(x.SharedInboxRoute)) .ToList(); - await ProcessFollowersWithSharedInboxAsync(userWithTweetsToSync.Tweets, followersWtSharedInbox, user); + await ProcessFollowersWithSharedInboxAsync( + userWithTweetsToSync.Tweets, + followersWtSharedInbox, + user + ); // Process Inbox var followerWtInbox = userWithTweetsToSync.Followers .Where(x => string.IsNullOrWhiteSpace(x.SharedInboxRoute)) .ToList(); - await ProcessFollowersWithInboxAsync(userWithTweetsToSync.Tweets, followerWtInbox, user); + await ProcessFollowersWithInboxAsync( + userWithTweetsToSync.Tweets, + followerWtInbox, + user + ); return userWithTweetsToSync; } - private async Task ProcessFollowersWithSharedInboxAsync(ExtractedTweet[] tweets, List followers, SyncTwitterUser user) + private async Task ProcessFollowersWithSharedInboxAsync( + ExtractedTweet[] tweets, + List followers, + SyncTwitterUser user + ) { var followersPerInstances = followers.GroupBy(x => x.Host); @@ -62,7 +85,12 @@ namespace BirdsiteLive.Pipeline.Processors { try { - await _sendTweetsToSharedInbox.ExecuteAsync(tweets, user, followersPerInstance.Key, followersPerInstance.ToArray()); + await _sendTweetsToSharedInbox.ExecuteAsync( + tweets, + user, + followersPerInstance.Key, + followersPerInstance.ToArray() + ); foreach (var f in followersPerInstance) await ProcessWorkingUserAsync(f); @@ -70,15 +98,24 @@ namespace BirdsiteLive.Pipeline.Processors catch (Exception e) { var follower = followersPerInstance.First(); - _logger.LogError(e, "Posting to {Host}{Route} failed", follower.Host, follower.SharedInboxRoute); + _logger.LogError( + e, + "Posting to {Host}{Route} failed", + follower.Host, + follower.SharedInboxRoute + ); foreach (var f in followersPerInstance) await ProcessFailingUserAsync(f); } } } - - private async Task ProcessFollowersWithInboxAsync(ExtractedTweet[] tweets, List followerWtInbox, SyncTwitterUser user) + + private async Task ProcessFollowersWithInboxAsync( + ExtractedTweet[] tweets, + List followerWtInbox, + SyncTwitterUser user + ) { foreach (var follower in followerWtInbox) { @@ -89,7 +126,12 @@ namespace BirdsiteLive.Pipeline.Processors } catch (Exception e) { - _logger.LogError(e, "Posting to {Host}{Route} failed", follower.Host, follower.InboxRoute); + _logger.LogError( + e, + "Posting to {Host}{Route} failed", + follower.Host, + follower.InboxRoute + ); await ProcessFailingUserAsync(follower); } } @@ -110,4 +152,4 @@ namespace BirdsiteLive.Pipeline.Processors await _followersDal.UpdateFollowerAsync(follower); } } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive.Pipeline/Processors/SubTasks/SendTweetsToInboxTask.cs b/src/BirdsiteLive.Pipeline/Processors/SubTasks/SendTweetsToInboxTask.cs index a6f6982..6f9d09c 100644 --- a/src/BirdsiteLive.Pipeline/Processors/SubTasks/SendTweetsToInboxTask.cs +++ b/src/BirdsiteLive.Pipeline/Processors/SubTasks/SendTweetsToInboxTask.cs @@ -1,20 +1,26 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Threading.Tasks; + using BirdsiteLive.Common.Settings; using BirdsiteLive.DAL.Contracts; using BirdsiteLive.DAL.Models; using BirdsiteLive.Domain; using BirdsiteLive.Twitter.Models; + using Microsoft.Extensions.Logging; namespace BirdsiteLive.Pipeline.Processors.SubTasks { public interface ISendTweetsToInboxTask { - Task ExecuteAsync(IEnumerable tweets, Follower follower, SyncTwitterUser user); + Task ExecuteAsync( + IEnumerable tweets, + Follower follower, + SyncTwitterUser user + ); } public class SendTweetsToInboxTask : ISendTweetsToInboxTask @@ -25,9 +31,14 @@ namespace BirdsiteLive.Pipeline.Processors.SubTasks private readonly InstanceSettings _settings; private readonly ILogger _logger; - #region Ctor - public SendTweetsToInboxTask(IActivityPubService activityPubService, IStatusService statusService, IFollowersDal followersDal, InstanceSettings settings, ILogger logger) + public SendTweetsToInboxTask( + IActivityPubService activityPubService, + IStatusService statusService, + IFollowersDal followersDal, + InstanceSettings settings, + ILogger logger + ) { _activityPubService = activityPubService; _statusService = statusService; @@ -37,14 +48,15 @@ namespace BirdsiteLive.Pipeline.Processors.SubTasks } #endregion - public async Task ExecuteAsync(IEnumerable tweets, Follower follower, SyncTwitterUser user) + public async Task ExecuteAsync( + IEnumerable tweets, + Follower follower, + SyncTwitterUser user + ) { var userId = user.Id; var fromStatusId = follower.FollowingsSyncStatus[userId]; - var tweetsToSend = tweets - .Where(x => x.Id > fromStatusId) - .OrderBy(x => x.Id) - .ToList(); + var tweetsToSend = tweets.Where(x => x.Id > fromStatusId).OrderBy(x => x.Id).ToList(); var inbox = follower.InboxRoute; @@ -55,19 +67,34 @@ namespace BirdsiteLive.Pipeline.Processors.SubTasks { try { - if (!tweet.IsReply || - tweet.IsReply && tweet.IsThread || - _settings.PublishReplies) + if ( + !tweet.IsReply + || tweet.IsReply && tweet.IsThread + || _settings.PublishReplies + ) { var note = _statusService.GetStatus(user.Acct, tweet); - await _activityPubService.PostNewNoteActivity(note, user.Acct, tweet.Id.ToString(), follower.Host, inbox); + await _activityPubService.PostNewNoteActivity( + note, + user.Acct, + tweet.Id.ToString(), + follower.Host, + inbox + ); } } catch (ArgumentException e) { - if (e.Message.Contains("Invalid pattern") && e.Message.Contains("at offset")) //Regex exception + if ( + e.Message.Contains("Invalid pattern") && e.Message.Contains("at offset") + ) //Regex exception { - _logger.LogError(e, "Can't parse {MessageContent} from Tweet {Id}", tweet.MessageContent, tweet.Id); + _logger.LogError( + e, + "Can't parse {MessageContent} from Tweet {Id}", + tweet.MessageContent, + tweet.Id + ); } else { @@ -88,4 +115,4 @@ namespace BirdsiteLive.Pipeline.Processors.SubTasks } } } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive.Pipeline/Processors/SubTasks/SendTweetsToSharedInboxTask.cs b/src/BirdsiteLive.Pipeline/Processors/SubTasks/SendTweetsToSharedInboxTask.cs index 1abe183..976fbaa 100644 --- a/src/BirdsiteLive.Pipeline/Processors/SubTasks/SendTweetsToSharedInboxTask.cs +++ b/src/BirdsiteLive.Pipeline/Processors/SubTasks/SendTweetsToSharedInboxTask.cs @@ -1,19 +1,26 @@ -using System; +using System; using System.Linq; using System.Net; using System.Threading.Tasks; + using BirdsiteLive.Common.Settings; using BirdsiteLive.DAL.Contracts; using BirdsiteLive.DAL.Models; using BirdsiteLive.Domain; using BirdsiteLive.Twitter.Models; + using Microsoft.Extensions.Logging; namespace BirdsiteLive.Pipeline.Processors.SubTasks { public interface ISendTweetsToSharedInboxTask { - Task ExecuteAsync(ExtractedTweet[] tweets, SyncTwitterUser user, string host, Follower[] followersPerInstance); + Task ExecuteAsync( + ExtractedTweet[] tweets, + SyncTwitterUser user, + string host, + Follower[] followersPerInstance + ); } public class SendTweetsToSharedInboxTask : ISendTweetsToSharedInboxTask @@ -25,7 +32,13 @@ namespace BirdsiteLive.Pipeline.Processors.SubTasks private readonly ILogger _logger; #region Ctor - public SendTweetsToSharedInboxTask(IActivityPubService activityPubService, IStatusService statusService, IFollowersDal followersDal, InstanceSettings settings, ILogger logger) + public SendTweetsToSharedInboxTask( + IActivityPubService activityPubService, + IStatusService statusService, + IFollowersDal followersDal, + InstanceSettings settings, + ILogger logger + ) { _activityPubService = activityPubService; _statusService = statusService; @@ -35,18 +48,19 @@ namespace BirdsiteLive.Pipeline.Processors.SubTasks } #endregion - public async Task ExecuteAsync(ExtractedTweet[] tweets, SyncTwitterUser user, string host, Follower[] followersPerInstance) + public async Task ExecuteAsync( + ExtractedTweet[] tweets, + SyncTwitterUser user, + string host, + Follower[] followersPerInstance + ) { var userId = user.Id; var inbox = followersPerInstance.First().SharedInboxRoute; - var fromStatusId = followersPerInstance - .Max(x => x.FollowingsSyncStatus[userId]); + var fromStatusId = followersPerInstance.Max(x => x.FollowingsSyncStatus[userId]); - var tweetsToSend = tweets - .Where(x => x.Id > fromStatusId) - .OrderBy(x => x.Id) - .ToList(); + var tweetsToSend = tweets.Where(x => x.Id > fromStatusId).OrderBy(x => x.Id).ToList(); var syncStatus = fromStatusId; try @@ -55,19 +69,34 @@ namespace BirdsiteLive.Pipeline.Processors.SubTasks { try { - if (!tweet.IsReply || - tweet.IsReply && tweet.IsThread || - _settings.PublishReplies) + if ( + !tweet.IsReply + || tweet.IsReply && tweet.IsThread + || _settings.PublishReplies + ) { var note = _statusService.GetStatus(user.Acct, tweet); - await _activityPubService.PostNewNoteActivity(note, user.Acct, tweet.Id.ToString(), host, inbox); + await _activityPubService.PostNewNoteActivity( + note, + user.Acct, + tweet.Id.ToString(), + host, + inbox + ); } } catch (ArgumentException e) { - if (e.Message.Contains("Invalid pattern") && e.Message.Contains("at offset")) //Regex exception + if ( + e.Message.Contains("Invalid pattern") && e.Message.Contains("at offset") + ) //Regex exception { - _logger.LogError(e, "Can't parse {MessageContent} from Tweet {Id}", tweet.MessageContent, tweet.Id); + _logger.LogError( + e, + "Can't parse {MessageContent} from Tweet {Id}", + tweet.MessageContent, + tweet.Id + ); } else { @@ -91,4 +120,4 @@ namespace BirdsiteLive.Pipeline.Processors.SubTasks } } } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive.Pipeline/StatusPublicationPipeline.cs b/src/BirdsiteLive.Pipeline/StatusPublicationPipeline.cs index c6917e7..89ed892 100644 --- a/src/BirdsiteLive.Pipeline/StatusPublicationPipeline.cs +++ b/src/BirdsiteLive.Pipeline/StatusPublicationPipeline.cs @@ -1,11 +1,13 @@ -using System; +using System; using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; using System.Threading.Tasks.Dataflow; + using BirdsiteLive.DAL.Models; using BirdsiteLive.Pipeline.Contracts; using BirdsiteLive.Pipeline.Models; + using Microsoft.Extensions.Logging; namespace BirdsiteLive.Pipeline @@ -26,7 +28,15 @@ namespace BirdsiteLive.Pipeline private readonly ILogger _logger; #region Ctor - public StatusPublicationPipeline(IRetrieveTweetsProcessor retrieveTweetsProcessor, IRetrieveTwitterUsersProcessor retrieveTwitterAccountsProcessor, IRetrieveFollowersProcessor retrieveFollowersProcessor, ISendTweetsToFollowersProcessor sendTweetsToFollowersProcessor, ISaveProgressionProcessor saveProgressionProcessor, IRefreshTwitterUserStatusProcessor refreshTwitterUserStatusProcessor, ILogger logger) + public StatusPublicationPipeline( + IRetrieveTweetsProcessor retrieveTweetsProcessor, + IRetrieveTwitterUsersProcessor retrieveTwitterAccountsProcessor, + IRetrieveFollowersProcessor retrieveFollowersProcessor, + ISendTweetsToFollowersProcessor sendTweetsToFollowersProcessor, + ISaveProgressionProcessor saveProgressionProcessor, + IRefreshTwitterUserStatusProcessor refreshTwitterUserStatusProcessor, + ILogger logger + ) { _retrieveTweetsProcessor = retrieveTweetsProcessor; _retrieveTwitterAccountsProcessor = retrieveTwitterAccountsProcessor; @@ -41,37 +51,107 @@ namespace BirdsiteLive.Pipeline public async Task ExecuteAsync(CancellationToken ct) { - // Create blocks - var twitterUserToRefreshBufferBlock = new BufferBlock(new DataflowBlockOptions - { BoundedCapacity = 1, CancellationToken = ct }); - var twitterUserToRefreshBlock = new TransformBlock(async x => await _refreshTwitterUserStatusProcessor.ProcessAsync(x, ct)); - var twitterUsersBufferBlock = new BufferBlock(new DataflowBlockOptions { BoundedCapacity = 1, CancellationToken = ct }); - var retrieveTweetsBlock = new TransformBlock(async x => await _retrieveTweetsProcessor.ProcessAsync(x, ct)); - var retrieveTweetsBufferBlock = new BufferBlock(new DataflowBlockOptions { BoundedCapacity = 1, CancellationToken = ct }); - var retrieveFollowersBlock = new TransformManyBlock(async x => await _retrieveFollowersProcessor.ProcessAsync(x, ct)); - var retrieveFollowersBufferBlock = new BufferBlock(new DataflowBlockOptions { BoundedCapacity = 20, CancellationToken = ct }); - var sendTweetsToFollowersBlock = new TransformBlock(async x => await _sendTweetsToFollowersProcessor.ProcessAsync(x, ct), new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = 5, CancellationToken = ct }); - var sendTweetsToFollowersBufferBlock = new BufferBlock(new DataflowBlockOptions { BoundedCapacity = 20, CancellationToken = ct }); - var saveProgressionBlock = new ActionBlock(async x => await _saveProgressionProcessor.ProcessAsync(x, ct), new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = 5, CancellationToken = ct }); + // Create blocks + var twitterUserToRefreshBufferBlock = new BufferBlock( + new DataflowBlockOptions { BoundedCapacity = 1, CancellationToken = ct } + ); + var twitterUserToRefreshBlock = new TransformBlock< + SyncTwitterUser[], + UserWithDataToSync[] + >(async x => await _refreshTwitterUserStatusProcessor.ProcessAsync(x, ct)); + var twitterUsersBufferBlock = new BufferBlock( + new DataflowBlockOptions { BoundedCapacity = 1, CancellationToken = ct } + ); + var retrieveTweetsBlock = new TransformBlock< + UserWithDataToSync[], + UserWithDataToSync[] + >(async x => await _retrieveTweetsProcessor.ProcessAsync(x, ct)); + var retrieveTweetsBufferBlock = new BufferBlock( + new DataflowBlockOptions { BoundedCapacity = 1, CancellationToken = ct } + ); + var retrieveFollowersBlock = new TransformManyBlock< + UserWithDataToSync[], + UserWithDataToSync + >(async x => await _retrieveFollowersProcessor.ProcessAsync(x, ct)); + var retrieveFollowersBufferBlock = new BufferBlock( + new DataflowBlockOptions { BoundedCapacity = 20, CancellationToken = ct } + ); + var sendTweetsToFollowersBlock = new TransformBlock< + UserWithDataToSync, + UserWithDataToSync + >( + async x => await _sendTweetsToFollowersProcessor.ProcessAsync(x, ct), + new ExecutionDataflowBlockOptions + { + MaxDegreeOfParallelism = 5, + CancellationToken = ct + } + ); + var sendTweetsToFollowersBufferBlock = new BufferBlock( + new DataflowBlockOptions { BoundedCapacity = 20, CancellationToken = ct } + ); + var saveProgressionBlock = new ActionBlock( + async x => await _saveProgressionProcessor.ProcessAsync(x, ct), + new ExecutionDataflowBlockOptions + { + MaxDegreeOfParallelism = 5, + CancellationToken = ct + } + ); // Link pipeline - twitterUserToRefreshBufferBlock.LinkTo(twitterUserToRefreshBlock, new DataflowLinkOptions { PropagateCompletion = true }); - twitterUserToRefreshBlock.LinkTo(twitterUsersBufferBlock, new DataflowLinkOptions { PropagateCompletion = true }); - twitterUsersBufferBlock.LinkTo(retrieveTweetsBlock, new DataflowLinkOptions { PropagateCompletion = true }); - retrieveTweetsBlock.LinkTo(retrieveTweetsBufferBlock, new DataflowLinkOptions { PropagateCompletion = true }); - retrieveTweetsBufferBlock.LinkTo(retrieveFollowersBlock, new DataflowLinkOptions { PropagateCompletion = true }); - retrieveFollowersBlock.LinkTo(retrieveFollowersBufferBlock, new DataflowLinkOptions { PropagateCompletion = true }); - retrieveFollowersBufferBlock.LinkTo(sendTweetsToFollowersBlock, new DataflowLinkOptions { PropagateCompletion = true }); - sendTweetsToFollowersBlock.LinkTo(sendTweetsToFollowersBufferBlock, new DataflowLinkOptions { PropagateCompletion = true }); - sendTweetsToFollowersBufferBlock.LinkTo(saveProgressionBlock, new DataflowLinkOptions { PropagateCompletion = true }); + twitterUserToRefreshBufferBlock.LinkTo( + twitterUserToRefreshBlock, + new DataflowLinkOptions { PropagateCompletion = true } + ); + twitterUserToRefreshBlock.LinkTo( + twitterUsersBufferBlock, + new DataflowLinkOptions { PropagateCompletion = true } + ); + twitterUsersBufferBlock.LinkTo( + retrieveTweetsBlock, + new DataflowLinkOptions { PropagateCompletion = true } + ); + retrieveTweetsBlock.LinkTo( + retrieveTweetsBufferBlock, + new DataflowLinkOptions { PropagateCompletion = true } + ); + retrieveTweetsBufferBlock.LinkTo( + retrieveFollowersBlock, + new DataflowLinkOptions { PropagateCompletion = true } + ); + retrieveFollowersBlock.LinkTo( + retrieveFollowersBufferBlock, + new DataflowLinkOptions { PropagateCompletion = true } + ); + retrieveFollowersBufferBlock.LinkTo( + sendTweetsToFollowersBlock, + new DataflowLinkOptions { PropagateCompletion = true } + ); + sendTweetsToFollowersBlock.LinkTo( + sendTweetsToFollowersBufferBlock, + new DataflowLinkOptions { PropagateCompletion = true } + ); + sendTweetsToFollowersBufferBlock.LinkTo( + saveProgressionBlock, + new DataflowLinkOptions { PropagateCompletion = true } + ); // Launch twitter user retriever - var retrieveTwitterAccountsTask = _retrieveTwitterAccountsProcessor.GetTwitterUsersAsync(twitterUserToRefreshBufferBlock, ct); + var retrieveTwitterAccountsTask = + _retrieveTwitterAccountsProcessor.GetTwitterUsersAsync( + twitterUserToRefreshBufferBlock, + ct + ); // Wait - await Task.WhenAny(new[] { retrieveTwitterAccountsTask, saveProgressionBlock.Completion }); + await Task.WhenAny( + new[] { retrieveTwitterAccountsTask, saveProgressionBlock.Completion } + ); - var ex = retrieveTwitterAccountsTask.IsFaulted ? retrieveTwitterAccountsTask.Exception : saveProgressionBlock.Completion.Exception; + var ex = retrieveTwitterAccountsTask.IsFaulted + ? retrieveTwitterAccountsTask.Exception + : saveProgressionBlock.Completion.Exception; _logger.LogCritical(ex, "An error occurred, pipeline stopped"); } } diff --git a/src/BirdsiteLive.Pipeline/Tools/MaxUsersNumberProvider.cs b/src/BirdsiteLive.Pipeline/Tools/MaxUsersNumberProvider.cs index 1c7e7c4..0aa0b77 100644 --- a/src/BirdsiteLive.Pipeline/Tools/MaxUsersNumberProvider.cs +++ b/src/BirdsiteLive.Pipeline/Tools/MaxUsersNumberProvider.cs @@ -1,4 +1,5 @@ -using System.Threading.Tasks; +using System.Threading.Tasks; + using BirdsiteLive.Common.Settings; using BirdsiteLive.DAL.Contracts; @@ -13,13 +14,16 @@ namespace BirdsiteLive.Pipeline.Tools { private readonly InstanceSettings _instanceSettings; private readonly ITwitterUserDal _twitterUserDal; - + private int _totalUsersCount = -1; private int _warmUpIterations; private const int WarmUpMaxCapacity = 200; #region Ctor - public MaxUsersNumberProvider(InstanceSettings instanceSettings, ITwitterUserDal twitterUserDal) + public MaxUsersNumberProvider( + InstanceSettings instanceSettings, + ITwitterUserDal twitterUserDal + ) { _instanceSettings = instanceSettings; _twitterUserDal = twitterUserDal; @@ -29,21 +33,21 @@ namespace BirdsiteLive.Pipeline.Tools public async Task GetMaxUsersNumberAsync() { // Init data - if (_totalUsersCount == -1) + if (_totalUsersCount == -1) { _totalUsersCount = await _twitterUserDal.GetTwitterUsersCountAsync(); _warmUpIterations = (int)(_totalUsersCount / (float)WarmUpMaxCapacity); } // Return if warm up ended - if (_warmUpIterations <= 0) return _instanceSettings.MaxUsersCapacity; + if (_warmUpIterations <= 0) + return _instanceSettings.MaxUsersCapacity; // Calculate warm up value - var maxUsers = _warmUpIterations > 0 - ? WarmUpMaxCapacity - : _instanceSettings.MaxUsersCapacity; + var maxUsers = + _warmUpIterations > 0 ? WarmUpMaxCapacity : _instanceSettings.MaxUsersCapacity; _warmUpIterations--; return maxUsers; } } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive.Twitter/BirdsiteLive.Twitter.csproj b/src/BirdsiteLive.Twitter/BirdsiteLive.Twitter.csproj index 438b4e1..45c4ce9 100644 --- a/src/BirdsiteLive.Twitter/BirdsiteLive.Twitter.csproj +++ b/src/BirdsiteLive.Twitter/BirdsiteLive.Twitter.csproj @@ -1,7 +1,7 @@ - netstandard2.0 + net6.0 diff --git a/src/BirdsiteLive.Twitter/CachedTwitterTweetService.cs b/src/BirdsiteLive.Twitter/CachedTwitterTweetService.cs index 252a61d..c3d8f61 100644 --- a/src/BirdsiteLive.Twitter/CachedTwitterTweetService.cs +++ b/src/BirdsiteLive.Twitter/CachedTwitterTweetService.cs @@ -1,5 +1,7 @@ -using System; +using System; + using BirdsiteLive.Twitter.Models; + using Microsoft.Extensions.Caching.Memory; namespace BirdsiteLive.Twitter @@ -13,13 +15,12 @@ namespace BirdsiteLive.Twitter { private readonly ITwitterTweetsService _twitterService; - private MemoryCache _tweetCache = new MemoryCache(new MemoryCacheOptions() - { - SizeLimit = 5000 - }); + private MemoryCache _tweetCache = new MemoryCache( + new MemoryCacheOptions() { SizeLimit = 5000 } + ); private MemoryCacheEntryOptions _cacheEntryOptions = new MemoryCacheEntryOptions() - .SetSize(1)//Size amount - //Priority on removing when reaching size limit (memory pressure) + .SetSize(1) //Size amount + //Priority on removing when reaching size limit (memory pressure) .SetPriority(CacheItemPriority.High) // Keep in cache for this time, reset time if accessed. // We set this lower than a user's in case they delete this Tweet for some reason; we don't need that cached. @@ -42,13 +43,13 @@ namespace BirdsiteLive.Twitter public ExtractedTweet GetTweet(long statusId) { - if(!_tweetCache.TryGetValue(statusId, out ExtractedTweet tweet)) + if (!_tweetCache.TryGetValue(statusId, out ExtractedTweet tweet)) { tweet = _twitterService.GetTweet(statusId); // Unlike with the user cache, save the null value anyway to prevent (quicker) API exhaustion. // It's incredibly unlikely that a tweet with this ID is going to magickally appear within 2 hours. - _tweetCache.Set(statusId, tweet, _cacheEntryOptions); + _tweetCache.Set(statusId, tweet, _cacheEntryOptions); } return tweet; @@ -60,4 +61,4 @@ namespace BirdsiteLive.Twitter _tweetCache.Remove(statusId); } } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive.Twitter/CachedTwitterUserService.cs b/src/BirdsiteLive.Twitter/CachedTwitterUserService.cs index ac20a62..5a910de 100644 --- a/src/BirdsiteLive.Twitter/CachedTwitterUserService.cs +++ b/src/BirdsiteLive.Twitter/CachedTwitterUserService.cs @@ -1,5 +1,7 @@ -using System; +using System; + using BirdsiteLive.Twitter.Models; + using Microsoft.Extensions.Caching.Memory; namespace BirdsiteLive.Twitter @@ -13,12 +15,11 @@ namespace BirdsiteLive.Twitter { private readonly ITwitterUserService _twitterService; - private MemoryCache _userCache = new MemoryCache(new MemoryCacheOptions() - { - SizeLimit = 5000 - }); + private MemoryCache _userCache = new MemoryCache( + new MemoryCacheOptions() { SizeLimit = 5000 } + ); private MemoryCacheEntryOptions _cacheEntryOptions = new MemoryCacheEntryOptions() - .SetSize(1)//Size amount + .SetSize(1) //Size amount //Priority on removing when reaching size limit (memory pressure) .SetPriority(CacheItemPriority.High) // Keep in cache for this time, reset time if accessed. @@ -38,7 +39,8 @@ namespace BirdsiteLive.Twitter if (!_userCache.TryGetValue(username, out TwitterUser user)) { user = _twitterService.GetUser(username); - if(user != null) _userCache.Set(username, user, _cacheEntryOptions); + if (user != null) + _userCache.Set(username, user, _cacheEntryOptions); } return user; @@ -49,4 +51,4 @@ namespace BirdsiteLive.Twitter _userCache.Remove(username); } } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive.Twitter/Extractors/TweetExtractor.cs b/src/BirdsiteLive.Twitter/Extractors/TweetExtractor.cs index a44f6bb..f0727f7 100644 --- a/src/BirdsiteLive.Twitter/Extractors/TweetExtractor.cs +++ b/src/BirdsiteLive.Twitter/Extractors/TweetExtractor.cs @@ -1,9 +1,11 @@ -using System; +using System; using System.Collections.Generic; using System.IO; using System.Linq; + using BirdsiteLive.Common.Settings; using BirdsiteLive.Twitter.Models; + using Tweetinvi.Models; using Tweetinvi.Models.Entities; @@ -36,11 +38,20 @@ namespace BirdsiteLive.Twitter.Extractors Media = ExtractMedia(tweet), CreatedAt = tweet.CreatedAt.ToUniversalTime(), IsReply = tweet.InReplyToUserId != null, - IsThread = tweet.InReplyToUserId != null && tweet.InReplyToUserId == tweet.CreatedBy.Id, + IsThread = + tweet.InReplyToUserId != null && tweet.InReplyToUserId == tweet.CreatedBy.Id, IsRetweet = tweet.IsRetweet || tweet.QuotedStatusId != null, RetweetUrl = ExtractRetweetUrl(tweet), IsSensitive = tweet.PossiblySensitive, - QuoteTweetUrl = tweet.QuotedStatusId != null ? "https://" + _instanceSettings.Domain + "/users/" + tweet.QuotedTweet.CreatedBy.ScreenName + "/statuses/" + tweet.QuotedStatusId : null + QuoteTweetUrl = + tweet.QuotedStatusId != null + ? "https://" + + _instanceSettings.Domain + + "/users/" + + tweet.QuotedTweet.CreatedBy.ScreenName + + "/statuses/" + + tweet.QuotedStatusId + : null }; return extractedTweet; @@ -59,7 +70,9 @@ namespace BirdsiteLive.Twitter.Extractors } if (tweet.FullText.Contains("https://t.co/")) { - var retweetId = tweet.FullText.Split(new[] { "https://t.co/" }, StringSplitOptions.RemoveEmptyEntries).Last(); + var retweetId = tweet.FullText + .Split(new[] { "https://t.co/" }, StringSplitOptions.RemoveEmptyEntries) + .Last(); return $"https://t.co/{retweetId}"; } } @@ -71,7 +84,7 @@ namespace BirdsiteLive.Twitter.Extractors { var message = tweet.FullText; var tweetUrls = tweet.Media.Select(x => x.URL).Distinct(); - + if (tweet.IsRetweet && message.StartsWith("RT") && tweet.RetweetedTweet != null) { message = tweet.RetweetedTweet.FullText; @@ -80,13 +93,13 @@ namespace BirdsiteLive.Twitter.Extractors foreach (var tweetUrl in tweetUrls) { - if(tweet.IsRetweet) + if (tweet.IsRetweet) message = tweet.RetweetedTweet.FullText.Replace(tweetUrl, string.Empty).Trim(); - else + else message = message.Replace(tweetUrl, string.Empty).Trim(); } - if (tweet.QuotedTweet != null && ! _instanceSettings.EnableQuoteRT) + if (tweet.QuotedTweet != null && !_instanceSettings.EnableQuoteRT) { message = $"[Quote {{RT}}]{Environment.NewLine}{message}"; } @@ -94,9 +107,16 @@ namespace BirdsiteLive.Twitter.Extractors if (tweet.IsRetweet) { if (tweet.RetweetedTweet != null && !message.StartsWith("RT")) - message = $"[{{RT}} @{tweet.RetweetedTweet.CreatedBy.ScreenName}]{Environment.NewLine}{message}"; - else if (tweet.RetweetedTweet != null && message.StartsWith($"RT @{tweet.RetweetedTweet.CreatedBy.ScreenName}:")) - message = message.Replace($"RT @{tweet.RetweetedTweet.CreatedBy.ScreenName}:", $"[{{RT}} @{tweet.RetweetedTweet.CreatedBy.ScreenName}]{Environment.NewLine}"); + message = + $"[{{RT}} @{tweet.RetweetedTweet.CreatedBy.ScreenName}]{Environment.NewLine}{message}"; + else if ( + tweet.RetweetedTweet != null + && message.StartsWith($"RT @{tweet.RetweetedTweet.CreatedBy.ScreenName}:") + ) + message = message.Replace( + $"RT @{tweet.RetweetedTweet.CreatedBy.ScreenName}:", + $"[{{RT}} @{tweet.RetweetedTweet.CreatedBy.ScreenName}]{Environment.NewLine}" + ); else message = message.Replace("RT", "[{{RT}}]"); } @@ -108,7 +128,8 @@ namespace BirdsiteLive.Twitter.Extractors if (url.ExpandedURL == tweet.QuotedTweet?.Url && _instanceSettings.EnableQuoteRT) { url.ExpandedURL = ""; - } else + } + else { var linkUri = new UriBuilder(url.ExpandedURL); @@ -138,14 +159,10 @@ namespace BirdsiteLive.Twitter.Extractors { var mediaUrl = GetMediaUrl(m); var mediaType = GetMediaType(m.MediaType, mediaUrl); - if (mediaType == null) continue; + if (mediaType == null) + continue; - - var att = new ExtractedMedia - { - MediaType = mediaType, - Url = mediaUrl - }; + var att = new ExtractedMedia { MediaType = mediaType, Url = mediaUrl }; result.Add(att); } @@ -156,10 +173,17 @@ namespace BirdsiteLive.Twitter.Extractors { switch (media.MediaType) { - case "photo": return media.MediaURLHttps; - case "animated_gif": return media.VideoDetails.Variants[0].URL; - case "video": return media.VideoDetails.Variants.OrderByDescending(x => x.Bitrate).First().URL; - default: return null; + case "photo": + return media.MediaURLHttps; + case "animated_gif": + return media.VideoDetails.Variants[0].URL; + case "video": + return media.VideoDetails.Variants + .OrderByDescending(x => x.Bitrate) + .First() + .URL; + default: + return null; } } @@ -195,4 +219,4 @@ namespace BirdsiteLive.Twitter.Extractors return null; } } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive.Twitter/Models/ApiStatistics.cs b/src/BirdsiteLive.Twitter/Models/ApiStatistics.cs index 4d5b194..f5f1152 100644 --- a/src/BirdsiteLive.Twitter/Models/ApiStatistics.cs +++ b/src/BirdsiteLive.Twitter/Models/ApiStatistics.cs @@ -1,4 +1,4 @@ -namespace BirdsiteLive.Twitter.Models +namespace BirdsiteLive.Twitter.Models { public class ApiStatistics { @@ -15,4 +15,4 @@ public int TimelineCallsCountMax { get; set; } public int TimelineCallsMax { get; set; } } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive.Twitter/Models/ExtractedMedia.cs b/src/BirdsiteLive.Twitter/Models/ExtractedMedia.cs index cdab034..1d4f11f 100644 --- a/src/BirdsiteLive.Twitter/Models/ExtractedMedia.cs +++ b/src/BirdsiteLive.Twitter/Models/ExtractedMedia.cs @@ -1,8 +1,8 @@ -namespace BirdsiteLive.Twitter.Models +namespace BirdsiteLive.Twitter.Models { public class ExtractedMedia { public string MediaType { get; set; } public string Url { get; set; } } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive.Twitter/Models/ExtractedTweet.cs b/src/BirdsiteLive.Twitter/Models/ExtractedTweet.cs index c9fa9b9..57a8597 100644 --- a/src/BirdsiteLive.Twitter/Models/ExtractedTweet.cs +++ b/src/BirdsiteLive.Twitter/Models/ExtractedTweet.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Net.Sockets; namespace BirdsiteLive.Twitter.Models @@ -18,4 +18,4 @@ namespace BirdsiteLive.Twitter.Models public bool IsSensitive { get; set; } public string QuoteTweetUrl { get; set; } } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive.Twitter/Models/TwitterUser.cs b/src/BirdsiteLive.Twitter/Models/TwitterUser.cs index 45a82ae..db29853 100644 --- a/src/BirdsiteLive.Twitter/Models/TwitterUser.cs +++ b/src/BirdsiteLive.Twitter/Models/TwitterUser.cs @@ -1,4 +1,4 @@ -namespace BirdsiteLive.Twitter.Models +namespace BirdsiteLive.Twitter.Models { public class TwitterUser { @@ -14,4 +14,4 @@ public bool Sensitive { get; set; } public bool Verified { get; set; } } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive.Twitter/Statistics/TwitterStatisticsHandler.cs b/src/BirdsiteLive.Twitter/Statistics/TwitterStatisticsHandler.cs index 668be76..d8e485c 100644 --- a/src/BirdsiteLive.Twitter/Statistics/TwitterStatisticsHandler.cs +++ b/src/BirdsiteLive.Twitter/Statistics/TwitterStatisticsHandler.cs @@ -1,8 +1,9 @@ -using System; +using System; using System.Collections.Concurrent; using System.Linq; using System.Threading; using System.Timers; + using BirdsiteLive.Twitter.Models; namespace BirdsiteLive.Statistics.Domain @@ -22,7 +23,8 @@ namespace BirdsiteLive.Statistics.Domain private static int _tweetCalls; private static int _timelineCalls; - private static ConcurrentDictionary _snapshots = new ConcurrentDictionary(); + private static ConcurrentDictionary _snapshots = + new ConcurrentDictionary(); private static System.Timers.Timer _resetTimer; @@ -48,29 +50,30 @@ namespace BirdsiteLive.Statistics.Domain { success = _snapshots.TryAdd(snapshot.SnapshotDate, snapshot); } while (!success); - + // Reset Interlocked.Exchange(ref _userCalls, 0); Interlocked.Exchange(ref _tweetCalls, 0); Interlocked.Exchange(ref _timelineCalls, 0); - // Clean up + // Clean up var now = DateTime.UtcNow; var oldSnapshots = _snapshots.Keys.Where(x => (now - x).TotalHours > 24).ToList(); - foreach (var old in oldSnapshots) _snapshots.TryRemove(old, out var data); + foreach (var old in oldSnapshots) + _snapshots.TryRemove(old, out var data); } - public void CalledUserApi() //GET users/show - 900/15mins + public void CalledUserApi() //GET users/show - 900/15mins { Interlocked.Increment(ref _userCalls); } - public void CalledTweetApi() //GET statuses/lookup - 300/15mins + public void CalledTweetApi() //GET statuses/lookup - 300/15mins { Interlocked.Increment(ref _tweetCalls); } - public void CalledTimelineApi() // GET statuses/user_timeline - 1500/15 mins + public void CalledTimelineApi() // GET statuses/user_timeline - 1500/15 mins { Interlocked.Increment(ref _timelineCalls); } @@ -100,7 +103,7 @@ namespace BirdsiteLive.Statistics.Domain } } - internal class ApiStatisticsSnapshot + internal class ApiStatisticsSnapshot { #region Ctor public ApiStatisticsSnapshot(int userCalls, int tweetCalls, int timelineCalls) @@ -112,9 +115,9 @@ namespace BirdsiteLive.Statistics.Domain } #endregion - public DateTime SnapshotDate { get; } + public DateTime SnapshotDate { get; } public int UserCalls { get; set; } public int TweetCalls { get; set; } public int TimelineCalls { get; set; } } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive.Twitter/Tools/TwitterAuthenticationInitializer.cs b/src/BirdsiteLive.Twitter/Tools/TwitterAuthenticationInitializer.cs index 8484c3d..8a0d55f 100644 --- a/src/BirdsiteLive.Twitter/Tools/TwitterAuthenticationInitializer.cs +++ b/src/BirdsiteLive.Twitter/Tools/TwitterAuthenticationInitializer.cs @@ -1,8 +1,11 @@ -using System; +using System; using System.Threading; using System.Threading.Tasks; + using BirdsiteLive.Common.Settings; + using Microsoft.Extensions.Logging; + using Tweetinvi; namespace BirdsiteLive.Twitter.Tools @@ -20,7 +23,10 @@ namespace BirdsiteLive.Twitter.Tools private readonly SemaphoreSlim _semaphoregate = new SemaphoreSlim(1); #region Ctor - public TwitterAuthenticationInitializer(TwitterSettings settings, ILogger logger) + public TwitterAuthenticationInitializer( + TwitterSettings settings, + ILogger logger + ) { _settings = settings; _logger = logger; @@ -29,12 +35,14 @@ namespace BirdsiteLive.Twitter.Tools public void EnsureAuthenticationIsInitialized() { - if (_initialized) return; + if (_initialized) + return; _semaphoregate.Wait(); - + try { - if (_initialized) return; + if (_initialized) + return; InitTwitterCredentials(); } finally @@ -45,11 +53,15 @@ namespace BirdsiteLive.Twitter.Tools private void InitTwitterCredentials() { - for (;;) + for (; ; ) { try { - Auth.SetApplicationOnlyCredentials(_settings.ConsumerKey, _settings.ConsumerSecret, true); + Auth.SetApplicationOnlyCredentials( + _settings.ConsumerKey, + _settings.ConsumerSecret, + true + ); _initialized = true; return; } @@ -61,4 +73,4 @@ namespace BirdsiteLive.Twitter.Tools } } } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive.Twitter/TwitterTweetsService.cs b/src/BirdsiteLive.Twitter/TwitterTweetsService.cs index 41b2d60..3c7fd63 100644 --- a/src/BirdsiteLive.Twitter/TwitterTweetsService.cs +++ b/src/BirdsiteLive.Twitter/TwitterTweetsService.cs @@ -1,12 +1,15 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; + using BirdsiteLive.Common.Settings; using BirdsiteLive.Statistics.Domain; using BirdsiteLive.Twitter.Extractors; using BirdsiteLive.Twitter.Models; using BirdsiteLive.Twitter.Tools; + using Microsoft.Extensions.Logging; + using Tweetinvi; using Tweetinvi.Models; using Tweetinvi.Parameters; @@ -28,7 +31,13 @@ namespace BirdsiteLive.Twitter private readonly ILogger _logger; #region Ctor - public TwitterTweetsService(ITwitterAuthenticationInitializer twitterAuthenticationInitializer, ITweetExtractor tweetExtractor, ITwitterStatisticsHandler statisticsHandler, ITwitterUserService twitterUserService, ILogger logger) + public TwitterTweetsService( + ITwitterAuthenticationInitializer twitterAuthenticationInitializer, + ITweetExtractor tweetExtractor, + ITwitterStatisticsHandler statisticsHandler, + ITwitterUserService twitterUserService, + ILogger logger + ) { _twitterAuthenticationInitializer = twitterAuthenticationInitializer; _tweetExtractor = tweetExtractor; @@ -48,7 +57,8 @@ namespace BirdsiteLive.Twitter var tweet = Tweet.GetTweet(statusId); _statisticsHandler.CalledTweetApi(); - if (tweet == null) return null; //TODO: test this + if (tweet == null) + return null; //TODO: test this return _tweetExtractor.Extract(tweet); } catch (Exception e) @@ -67,13 +77,15 @@ namespace BirdsiteLive.Twitter TweetinviConfig.CurrentThreadSettings.TweetMode = TweetMode.Extended; var user = _twitterUserService.GetUser(username); - if (user == null || user.Protected) return new ExtractedTweet[0]; + if (user == null || user.Protected) + return new ExtractedTweet[0]; if (fromTweetId == -1) { var timeline = Timeline.GetUserTimeline(user.Id, nberTweets); _statisticsHandler.CalledTimelineApi(); - if (timeline != null) tweets.AddRange(timeline); + if (timeline != null) + tweets.AddRange(timeline); } else { @@ -84,10 +96,11 @@ namespace BirdsiteLive.Twitter }; var timeline = Timeline.GetUserTimeline(user.Id, timelineRequestParameters); _statisticsHandler.CalledTimelineApi(); - if (timeline != null) tweets.AddRange(timeline); + if (timeline != null) + tweets.AddRange(timeline); } return tweets.Select(_tweetExtractor.Extract).ToArray(); } } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive.Twitter/TwitterUserService.cs b/src/BirdsiteLive.Twitter/TwitterUserService.cs index 166e466..f1ff50b 100644 --- a/src/BirdsiteLive.Twitter/TwitterUserService.cs +++ b/src/BirdsiteLive.Twitter/TwitterUserService.cs @@ -1,10 +1,13 @@ -using System; +using System; using System.Linq; + using BirdsiteLive.Common.Settings; using BirdsiteLive.Statistics.Domain; using BirdsiteLive.Twitter.Models; using BirdsiteLive.Twitter.Tools; + using Microsoft.Extensions.Logging; + using Tweetinvi; using Tweetinvi.Models; @@ -22,7 +25,11 @@ namespace BirdsiteLive.Twitter private readonly ILogger _logger; #region Ctor - public TwitterUserService(ITwitterAuthenticationInitializer twitterAuthenticationInitializer, ITwitterStatisticsHandler statisticsHandler, ILogger logger) + public TwitterUserService( + ITwitterAuthenticationInitializer twitterAuthenticationInitializer, + ITwitterStatisticsHandler statisticsHandler, + ILogger logger + ) { _twitterAuthenticationInitializer = twitterAuthenticationInitializer; _statisticsHandler = statisticsHandler; @@ -57,7 +64,11 @@ namespace BirdsiteLive.Twitter // Expand URLs var description = user.Description; - foreach (var descriptionUrl in user.Entities?.Description?.Urls?.OrderByDescending(x => x.URL.Length)) + foreach ( + var descriptionUrl in user.Entities?.Description?.Urls?.OrderByDescending( + x => x.URL.Length + ) + ) description = description.Replace(descriptionUrl.URL, descriptionUrl.ExpandedURL); return new TwitterUser @@ -75,4 +86,4 @@ namespace BirdsiteLive.Twitter }; } } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive.sln b/src/BirdsiteLive.sln index 4b0cfc1..c81b8cd 100644 --- a/src/BirdsiteLive.sln +++ b/src/BirdsiteLive.sln @@ -1,4 +1,4 @@ - + Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 16 VisualStudioVersion = 16.0.29911.84 diff --git a/src/BirdsiteLive/BirdsiteLive.csproj b/src/BirdsiteLive/BirdsiteLive.csproj index 5935a02..380f9e0 100644 --- a/src/BirdsiteLive/BirdsiteLive.csproj +++ b/src/BirdsiteLive/BirdsiteLive.csproj @@ -1,7 +1,7 @@ - + - netcoreapp3.1 + net6.0 d21486de-a812-47eb-a419-05682bb68856 Linux 0.19.1 diff --git a/src/BirdsiteLive/Component/NodeInfoViewComponent.cs b/src/BirdsiteLive/Component/NodeInfoViewComponent.cs index 34b1254..0d91cac 100644 --- a/src/BirdsiteLive/Component/NodeInfoViewComponent.cs +++ b/src/BirdsiteLive/Component/NodeInfoViewComponent.cs @@ -1,11 +1,13 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; + using BirdsiteLive.DAL.Contracts; using BirdsiteLive.Domain.Repository; using BirdsiteLive.Services; using BirdsiteLive.Statistics.Domain; + using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Razor.Language.Intermediate; @@ -15,9 +17,12 @@ namespace BirdsiteLive.Component { private readonly IModerationRepository _moderationRepository; private readonly IAboutPageService _cachedStatisticsService; - + #region Ctor - public NodeInfoViewComponent(IModerationRepository moderationRepository, IAboutPageService cachedStatisticsService) + public NodeInfoViewComponent( + IModerationRepository moderationRepository, + IAboutPageService cachedStatisticsService + ) { _moderationRepository = moderationRepository; _cachedStatisticsService = cachedStatisticsService; @@ -26,21 +31,27 @@ namespace BirdsiteLive.Component public async Task InvokeAsync() { - var followerPolicy = _moderationRepository.GetModerationType(ModerationEntityTypeEnum.Follower); - var twitterAccountPolicy = _moderationRepository.GetModerationType(ModerationEntityTypeEnum.TwitterAccount); + var followerPolicy = _moderationRepository.GetModerationType( + ModerationEntityTypeEnum.Follower + ); + var twitterAccountPolicy = _moderationRepository.GetModerationType( + ModerationEntityTypeEnum.TwitterAccount + ); var statistics = await _cachedStatisticsService.GetAboutPageDataAsync(); var viewModel = new NodeInfoViewModel { - BlacklistingEnabled = followerPolicy == ModerationTypeEnum.BlackListing || - twitterAccountPolicy == ModerationTypeEnum.BlackListing, - WhitelistingEnabled = followerPolicy == ModerationTypeEnum.WhiteListing || - twitterAccountPolicy == ModerationTypeEnum.WhiteListing, + BlacklistingEnabled = + followerPolicy == ModerationTypeEnum.BlackListing + || twitterAccountPolicy == ModerationTypeEnum.BlackListing, + WhitelistingEnabled = + followerPolicy == ModerationTypeEnum.WhiteListing + || twitterAccountPolicy == ModerationTypeEnum.WhiteListing, InstanceSaturation = statistics.Saturation, DiscloseRestrictions = statistics.Settings.DiscloseInstanceRestrictions }; - + //viewModel = new NodeInfoViewModel //{ // BlacklistingEnabled = false, diff --git a/src/BirdsiteLive/Controllers/AboutController.cs b/src/BirdsiteLive/Controllers/AboutController.cs index 3f0b6f4..c7c5273 100644 --- a/src/BirdsiteLive/Controllers/AboutController.cs +++ b/src/BirdsiteLive/Controllers/AboutController.cs @@ -1,11 +1,13 @@ -using Microsoft.AspNetCore.Mvc; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; + using BirdsiteLive.Domain.Repository; using BirdsiteLive.Services; +using Microsoft.AspNetCore.Mvc; + namespace BirdsiteLive.Controllers { public class AboutController : Controller @@ -25,6 +27,4 @@ namespace BirdsiteLive.Controllers return View(stats); } } - - } diff --git a/src/BirdsiteLive/Controllers/DebugingController.cs b/src/BirdsiteLive/Controllers/DebugingController.cs index 252486e..d13e220 100644 --- a/src/BirdsiteLive/Controllers/DebugingController.cs +++ b/src/BirdsiteLive/Controllers/DebugingController.cs @@ -1,15 +1,18 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Net.Http; using System.Text; using System.Threading.Tasks; + using BirdsiteLive.ActivityPub; using BirdsiteLive.ActivityPub.Models; using BirdsiteLive.Common.Settings; using BirdsiteLive.Domain; + using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.ViewFeatures; + using Newtonsoft.Json; namespace BirdsiteLive.Controllers @@ -22,7 +25,12 @@ namespace BirdsiteLive.Controllers private readonly IUserService _userService; #region Ctor - public DebugingController(InstanceSettings instanceSettings, ICryptoService cryptoService, IActivityPubService activityPubService, IUserService userService) + public DebugingController( + InstanceSettings instanceSettings, + ICryptoService cryptoService, + IActivityPubService activityPubService, + IUserService userService + ) { _instanceSettings = instanceSettings; _cryptoService = cryptoService; @@ -67,7 +75,7 @@ namespace BirdsiteLive.Controllers var noteGuid = Guid.NewGuid(); var noteId = $"https://{_instanceSettings.Domain}/users/{username}/statuses/{noteGuid}"; var noteUrl = $"https://{_instanceSettings.Domain}/@{username}/{noteGuid}"; - + var to = $"{actor}/followers"; var now = DateTime.UtcNow; @@ -80,21 +88,19 @@ namespace BirdsiteLive.Controllers type = "Create", actor = actor, published = nowString, - to = new []{ to }, + to = new[] { to }, //cc = new [] { "https://www.w3.org/ns/activitystreams#Public" }, apObject = new Note() { id = noteId, - summary = null, + summary = null, inReplyTo = null, published = nowString, url = noteUrl, attributedTo = actor, - // Unlisted to = new[] { to }, - cc = new [] { "https://www.w3.org/ns/activitystreams#Public" }, - + cc = new[] { "https://www.w3.org/ns/activitystreams#Public" }, //// Public //to = new[] { "https://www.w3.org/ns/activitystreams#Public" }, //cc = new[] { to }, @@ -137,4 +143,4 @@ namespace BirdsiteLive.Controllers #endif } } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive/Controllers/HomeController.cs b/src/BirdsiteLive/Controllers/HomeController.cs index e0d6855..332efe8 100644 --- a/src/BirdsiteLive/Controllers/HomeController.cs +++ b/src/BirdsiteLive/Controllers/HomeController.cs @@ -1,12 +1,14 @@ -using System; +using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Threading.Tasks; + +using BirdsiteLive.Common.Settings; +using BirdsiteLive.Models; + using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; -using BirdsiteLive.Models; -using BirdsiteLive.Common.Settings; namespace BirdsiteLive.Controllers { @@ -34,13 +36,18 @@ namespace BirdsiteLive.Controllers [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] public IActionResult Error() { - return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier }); + return View( + new ErrorViewModel + { + RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier + } + ); } [HttpPost] public IActionResult Index(string handle) { - return RedirectToAction("Index", "Users", new {id = handle}); + return RedirectToAction("Index", "Users", new { id = handle }); } } } diff --git a/src/BirdsiteLive/Controllers/InboxController.cs b/src/BirdsiteLive/Controllers/InboxController.cs index db055cf..887071d 100644 --- a/src/BirdsiteLive/Controllers/InboxController.cs +++ b/src/BirdsiteLive/Controllers/InboxController.cs @@ -1,8 +1,9 @@ -using System; +using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading.Tasks; + using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; @@ -32,10 +33,9 @@ namespace BirdsiteLive.Controllers _logger.LogTrace("Inbox: {Body}", body); //System.IO.File.WriteAllText($@"C:\apdebug\inbox\{Guid.NewGuid()}.json", body); - } return Accepted(); } } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive/Controllers/StatisticsController.cs b/src/BirdsiteLive/Controllers/StatisticsController.cs index 4078a31..1a75a1a 100644 --- a/src/BirdsiteLive/Controllers/StatisticsController.cs +++ b/src/BirdsiteLive/Controllers/StatisticsController.cs @@ -1,11 +1,13 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; + using BirdsiteLive.DAL.Contracts; using BirdsiteLive.Domain.Statistics; using BirdsiteLive.Statistics.Domain; + using Microsoft.AspNetCore.Mvc; namespace BirdsiteLive.Controllers @@ -18,7 +20,12 @@ namespace BirdsiteLive.Controllers private readonly IExtractionStatisticsHandler _extractionStatistics; #region Ctor - public StatisticsController(ITwitterUserDal twitterUserDal, IFollowersDal followersDal, ITwitterStatisticsHandler twitterStatistics, IExtractionStatisticsHandler extractionStatistics) + public StatisticsController( + ITwitterUserDal twitterUserDal, + IFollowersDal followersDal, + ITwitterStatisticsHandler twitterStatistics, + IExtractionStatisticsHandler extractionStatistics + ) { _twitterUserDal = twitterUserDal; _followersDal = followersDal; diff --git a/src/BirdsiteLive/Controllers/UsersController.cs b/src/BirdsiteLive/Controllers/UsersController.cs index 1a42eae..e08c36c 100644 --- a/src/BirdsiteLive/Controllers/UsersController.cs +++ b/src/BirdsiteLive/Controllers/UsersController.cs @@ -1,12 +1,10 @@ -using System; +using System; using System.Collections.Generic; using System.IO; using System.Linq; -using System.Net.Mime; -using System.Runtime.InteropServices.WindowsRuntime; using System.Text.RegularExpressions; -using System.Threading; using System.Threading.Tasks; + using BirdsiteLive.ActivityPub; using BirdsiteLive.ActivityPub.Models; using BirdsiteLive.Common.Regexes; @@ -15,10 +13,12 @@ using BirdsiteLive.Domain; using BirdsiteLive.Models; using BirdsiteLive.Twitter; using BirdsiteLive.Twitter.Models; + using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Primitives; + using Newtonsoft.Json; namespace BirdsiteLive.Controllers @@ -34,7 +34,15 @@ namespace BirdsiteLive.Controllers private readonly ILogger _logger; #region Ctor - public UsersController(ITwitterUserService twitterUserService, IUserService userService, IStatusService statusService, InstanceSettings instanceSettings, ITwitterTweetsService twitterTweetService, IActivityPubService activityPubService, ILogger logger) + public UsersController( + ITwitterUserService twitterUserService, + IUserService userService, + IStatusService statusService, + InstanceSettings instanceSettings, + ITwitterTweetsService twitterTweetService, + IActivityPubService activityPubService, + ILogger logger + ) { _twitterUserService = twitterUserService; _userService = userService; @@ -53,7 +61,8 @@ namespace BirdsiteLive.Controllers if (acceptHeaders.Any()) { var r = acceptHeaders.First(); - if (r.Contains("application/activity+json")) return NotFound(); + if (r.Contains("application/activity+json")) + return NotFound(); } return View("UserNotFound"); } @@ -67,29 +76,40 @@ namespace BirdsiteLive.Controllers id = id.Trim(new[] { ' ', '@' }).ToLowerInvariant(); - // Ensure valid username + // Ensure valid username // https://help.twitter.com/en/managing-your-account/twitter-username-rules TwitterUser user = null; - if (!string.IsNullOrWhiteSpace(id) && UserRegexes.TwitterAccount.IsMatch(id) && id.Length <= 15) + if ( + !string.IsNullOrWhiteSpace(id) + && UserRegexes.TwitterAccount.IsMatch(id) + && id.Length <= 15 + ) user = _twitterUserService.GetUser(id); var acceptHeaders = Request.Headers["Accept"]; if (acceptHeaders.Any()) { var r = acceptHeaders.First(); - if (r.Contains("application/activity+json")) + if ( + r.Contains("application/activity+json") + || r.Contains( + "application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\"" + ) + ) { - if (user == null) return NotFound(); + if (user == null) + return NotFound(); var apUser = _userService.GetUser(user); - var jsonApUser = JsonConvert.SerializeObject(apUser, new JsonSerializerSettings - { - NullValueHandling = NullValueHandling.Ignore - }); + var jsonApUser = JsonConvert.SerializeObject( + apUser, + new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore } + ); return Content(jsonApUser, "application/activity+json; charset=utf-8"); } } - if (user == null) return View("UserNotFound"); + if (user == null) + return View("UserNotFound"); var displayableUser = new DisplayTwitterUser { @@ -99,7 +119,6 @@ namespace BirdsiteLive.Controllers Url = user.Url, ProfileImageUrl = user.ProfileImageUrl, Protected = user.Protected, - InstanceHandle = $"@{user.Acct.ToLowerInvariant()}@{_instanceSettings.Domain}" }; return View(displayableUser); @@ -122,9 +141,11 @@ namespace BirdsiteLive.Controllers { // I hate bitwise operators, corn syrup, and the antichrist // shift 22 bits to the right to get milliseconds, add the twitter epoch, then divide by 1000 to get seconds - long secondsAgo = DateTimeOffset.UtcNow.ToUnixTimeSeconds() - (((parsedStatusId >> 22) + 1288834974657) / 1000); + long secondsAgo = + DateTimeOffset.UtcNow.ToUnixTimeSeconds() + - (((parsedStatusId >> 22) + 1288834974657) / 1000); - if ( secondsAgo > _instanceSettings.MaxStatusFetchAge*60*60*24 ) + if (secondsAgo > _instanceSettings.MaxStatusFetchAge * 60 * 60 * 24) { return new StatusCodeResult(StatusCodes.Status410Gone); } @@ -161,24 +182,42 @@ namespace BirdsiteLive.Controllers var activity = ApDeserializer.ProcessActivity(body); // Do something var signature = r.Headers["Signature"].First(); - + switch (activity?.type) { case "Follow": - { - var succeeded = await _userService.FollowRequestedAsync(signature, r.Method, r.Path, - r.QueryString.ToString(), RequestHeaders(r.Headers), activity as ActivityFollow, body); + { + var succeeded = await _userService.FollowRequestedAsync( + signature, + r.Method, + r.Path, + r.QueryString.ToString(), + RequestHeaders(r.Headers), + activity as ActivityFollow, + body + ); - if (succeeded) return Accepted(); - else return Unauthorized(); - } + if (succeeded) + return Accepted(); + else + return Unauthorized(); + } case "Undo": if (activity is ActivityUndoFollow) { - var succeeded = await _userService.UndoFollowRequestedAsync(signature, r.Method, r.Path, - r.QueryString.ToString(), RequestHeaders(r.Headers), activity as ActivityUndoFollow, body); - if (succeeded) return Accepted(); - else return Unauthorized(); + var succeeded = await _userService.UndoFollowRequestedAsync( + signature, + r.Method, + r.Path, + r.QueryString.ToString(), + RequestHeaders(r.Headers), + activity as ActivityUndoFollow, + body + ); + if (succeeded) + return Accepted(); + else + return Unauthorized(); } return Accepted(); default: @@ -192,7 +231,8 @@ namespace BirdsiteLive.Controllers public IActionResult Followers(string id) { var r = Request.Headers["Accept"].First(); - if (!r.Contains("application/activity+json")) return NotFound(); + if (!r.Contains("application/activity+json")) + return NotFound(); var followers = new Followers { @@ -204,7 +244,10 @@ namespace BirdsiteLive.Controllers private Dictionary RequestHeaders(IHeaderDictionary header) { - return header.ToDictionary, string, string>(h => h.Key.ToLowerInvariant(), h => h.Value); + return header.ToDictionary, string, string>( + h => h.Key.ToLowerInvariant(), + h => h.Value + ); } [Route("/users/{actor}/remote_follow")] @@ -213,15 +256,23 @@ namespace BirdsiteLive.Controllers { StringValues webfingerValues; - if (!Request.Form.TryGetValue("webfinger", out webfingerValues)) return BadRequest(); + if (!Request.Form.TryGetValue("webfinger", out webfingerValues)) + return BadRequest(); var webfinger = webfingerValues.First(); - if (webfinger.Length < 1 || actor.Length < 1) return BadRequest(); + if (webfinger.Length < 1 || actor.Length < 1) + return BadRequest(); - if (webfinger[0] == '@') webfinger = webfinger[1..]; + if (webfinger[0] == '@') + webfinger = webfinger[1..]; - if (webfinger.IndexOf("@") < 0 || ! new Regex("^[A-Za-z0-9_]*$").IsMatch(webfinger.Split('@')[0]) || ! new Regex("^[A-Za-z0-9_]*$").IsMatch(actor) || Uri.CheckHostName(webfinger.Split('@')[1]) == UriHostNameType.Unknown) + if ( + webfinger.IndexOf("@") < 0 + || !new Regex("^[A-Za-z0-9_]*$").IsMatch(webfinger.Split('@')[0]) + || !new Regex("^[A-Za-z0-9_]*$").IsMatch(actor) + || Uri.CheckHostName(webfinger.Split('@')[1]) == UriHostNameType.Unknown + ) { return BadRequest(); } @@ -232,7 +283,7 @@ namespace BirdsiteLive.Controllers { webfingerData = await _activityPubService.WebFinger(webfinger); } - catch(Exception e) + catch (Exception e) { _logger.LogError("Could not WebFinger {user}: {exception}", webfinger, e); return NotFound(); @@ -240,17 +291,24 @@ namespace BirdsiteLive.Controllers string redirectLink = ""; - foreach(var link in webfingerData.links) + foreach (var link in webfingerData.links) { - if(link.rel == "http://ostatus.org/schema/1.0/subscribe" && link.template.Length > 0) + if ( + link.rel == "http://ostatus.org/schema/1.0/subscribe" + && link.template.Length > 0 + ) { - redirectLink = link.template.Replace("{uri}", "https://" + _instanceSettings.Domain + "/users/" + actor); + redirectLink = link.template.Replace( + "{uri}", + "https://" + _instanceSettings.Domain + "/users/" + actor + ); } } - if (redirectLink == "") return NotFound(); + if (redirectLink == "") + return NotFound(); return Redirect(redirectLink); } } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive/Controllers/WellKnownController.cs b/src/BirdsiteLive/Controllers/WellKnownController.cs index 5b80abb..338ea9f 100644 --- a/src/BirdsiteLive/Controllers/WellKnownController.cs +++ b/src/BirdsiteLive/Controllers/WellKnownController.cs @@ -1,8 +1,9 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Text.RegularExpressions; using System.Threading.Tasks; + using BirdsiteLive.ActivityPub.Converters; using BirdsiteLive.Common.Regexes; using BirdsiteLive.Common.Settings; @@ -11,6 +12,7 @@ using BirdsiteLive.Domain.Repository; using BirdsiteLive.Models; using BirdsiteLive.Models.WellKnownModels; using BirdsiteLive.Twitter; + using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Options; @@ -25,7 +27,12 @@ namespace BirdsiteLive.Controllers private readonly InstanceSettings _settings; #region Ctor - public WellKnownController(InstanceSettings settings, ITwitterUserService twitterUserService, ITwitterUserDal twitterUserDal, IModerationRepository moderationRepository) + public WellKnownController( + InstanceSettings settings, + ITwitterUserService twitterUserService, + ITwitterUserDal twitterUserDal, + IModerationRepository moderationRepository + ) { _twitterUserService = twitterUserService; _twitterUserDal = twitterUserDal; @@ -60,7 +67,9 @@ namespace BirdsiteLive.Controllers public async Task NodeInfo(string id) { var twitterUsersCount = await _twitterUserDal.GetTwitterUsersCountAsync(); - var isOpenRegistration = _moderationRepository.GetModerationType(ModerationEntityTypeEnum.Follower) != ModerationTypeEnum.WhiteListing; + var isOpenRegistration = + _moderationRepository.GetModerationType(ModerationEntityTypeEnum.Follower) + != ModerationTypeEnum.WhiteListing; if (id == "2.0") { @@ -70,30 +79,17 @@ namespace BirdsiteLive.Controllers usage = new Usage() { localPosts = 0, - users = new Users() - { - total = twitterUsersCount - } - }, - software = new Software() - { - name = "birdsitelive", - version = Program.VERSION - }, - protocols = new[] - { - "activitypub" + users = new Users() { total = twitterUsersCount } }, + software = new Software() { name = "birdsitelive", version = Program.VERSION }, + protocols = new[] { "activitypub" }, openRegistrations = isOpenRegistration, services = new Models.WellKnownModels.Services() { inbound = new object[0], outbound = new object[0] }, - metadata = new Metadata() - { - email = _settings.AdminEmail - } + metadata = new Metadata() { email = _settings.AdminEmail } }; return new JsonResult(nodeInfo); } @@ -105,10 +101,7 @@ namespace BirdsiteLive.Controllers usage = new Usage() { localPosts = 0, - users = new Users() - { - total = twitterUsersCount - } + users = new Users() { total = twitterUsersCount } }, software = new SoftwareV21() { @@ -116,20 +109,14 @@ namespace BirdsiteLive.Controllers version = Program.VERSION, repository = "https://github.com/NicolasConstant/BirdsiteLive" }, - protocols = new[] - { - "activitypub" - }, + protocols = new[] { "activitypub" }, openRegistrations = isOpenRegistration, services = new Models.WellKnownModels.Services() { inbound = new object[0], outbound = new object[0] }, - metadata = new Metadata() - { - email = _settings.AdminEmail - } + metadata = new Metadata() { email = _settings.AdminEmail } }; return new JsonResult(nodeInfo); } @@ -165,9 +152,13 @@ namespace BirdsiteLive.Controllers // Ensure lowercase name = name.ToLowerInvariant(); - // Ensure valid username + // Ensure valid username // https://help.twitter.com/en/managing-your-account/twitter-username-rules - if (string.IsNullOrWhiteSpace(name) || !UserRegexes.TwitterAccount.IsMatch(name) || name.Length > 15 ) + if ( + string.IsNullOrWhiteSpace(name) + || !UserRegexes.TwitterAccount.IsMatch(name) + || name.Length > 15 + ) return NotFound(); if (!string.IsNullOrWhiteSpace(domain) && domain != _settings.Domain) @@ -182,10 +173,7 @@ namespace BirdsiteLive.Controllers var result = new WebFingerResult() { subject = $"acct:{name}@{_settings.Domain}", - aliases = new[] - { - actorUrl - }, + aliases = new[] { actorUrl }, links = new List { new WebFingerLink() @@ -206,4 +194,4 @@ namespace BirdsiteLive.Controllers return new JsonResult(result); } } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive/Models/DisplayTwitterUser.cs b/src/BirdsiteLive/Models/DisplayTwitterUser.cs index 3a93875..8ce8268 100644 --- a/src/BirdsiteLive/Models/DisplayTwitterUser.cs +++ b/src/BirdsiteLive/Models/DisplayTwitterUser.cs @@ -1,4 +1,4 @@ -namespace BirdsiteLive.Models +namespace BirdsiteLive.Models { public class DisplayTwitterUser { @@ -11,4 +11,4 @@ public string InstanceHandle { get; set; } } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive/Models/StatisticsModels/Statistics.cs b/src/BirdsiteLive/Models/StatisticsModels/Statistics.cs index 4a66f81..e48694e 100644 --- a/src/BirdsiteLive/Models/StatisticsModels/Statistics.cs +++ b/src/BirdsiteLive/Models/StatisticsModels/Statistics.cs @@ -1,4 +1,4 @@ -using BirdsiteLive.Domain.Statistics; +using BirdsiteLive.Domain.Statistics; using BirdsiteLive.Twitter.Models; namespace BirdsiteLive.Models.StatisticsModels @@ -12,4 +12,4 @@ namespace BirdsiteLive.Models.StatisticsModels public ApiStatistics TwitterStatistics { get; set; } public ExtractionStatistics ExtractionStatistics { get; set; } } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive/Models/WellKnownModels/Link.cs b/src/BirdsiteLive/Models/WellKnownModels/Link.cs index e4bedfe..ce00e45 100644 --- a/src/BirdsiteLive/Models/WellKnownModels/Link.cs +++ b/src/BirdsiteLive/Models/WellKnownModels/Link.cs @@ -1,8 +1,8 @@ -namespace BirdsiteLive.Models.WellKnownModels +namespace BirdsiteLive.Models.WellKnownModels { public class Link { public string href { get; set; } public string rel { get; set; } } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive/Models/WellKnownModels/Metadata.cs b/src/BirdsiteLive/Models/WellKnownModels/Metadata.cs index 9f5007e..b4b74a7 100644 --- a/src/BirdsiteLive/Models/WellKnownModels/Metadata.cs +++ b/src/BirdsiteLive/Models/WellKnownModels/Metadata.cs @@ -1,7 +1,7 @@ -namespace BirdsiteLive.Models.WellKnownModels +namespace BirdsiteLive.Models.WellKnownModels { public class Metadata { public string email { get; set; } } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive/Models/WellKnownModels/NodeInfoV20.cs b/src/BirdsiteLive/Models/WellKnownModels/NodeInfoV20.cs index 032fc51..fd6e537 100644 --- a/src/BirdsiteLive/Models/WellKnownModels/NodeInfoV20.cs +++ b/src/BirdsiteLive/Models/WellKnownModels/NodeInfoV20.cs @@ -1,4 +1,4 @@ -using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations; namespace BirdsiteLive.Models.WellKnownModels { @@ -12,4 +12,4 @@ namespace BirdsiteLive.Models.WellKnownModels public Services services { get; set; } public Metadata metadata { get; set; } } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive/Models/WellKnownModels/NodeInfoV21.cs b/src/BirdsiteLive/Models/WellKnownModels/NodeInfoV21.cs index ce397cb..abe53ce 100644 --- a/src/BirdsiteLive/Models/WellKnownModels/NodeInfoV21.cs +++ b/src/BirdsiteLive/Models/WellKnownModels/NodeInfoV21.cs @@ -1,4 +1,4 @@ -namespace BirdsiteLive.Models.WellKnownModels +namespace BirdsiteLive.Models.WellKnownModels { public class NodeInfoV21 { @@ -10,4 +10,4 @@ public Services services { get; set; } public Metadata metadata { get; set; } } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive/Models/WellKnownModels/Services.cs b/src/BirdsiteLive/Models/WellKnownModels/Services.cs index fa25074..88c6d16 100644 --- a/src/BirdsiteLive/Models/WellKnownModels/Services.cs +++ b/src/BirdsiteLive/Models/WellKnownModels/Services.cs @@ -1,8 +1,8 @@ -namespace BirdsiteLive.Models.WellKnownModels +namespace BirdsiteLive.Models.WellKnownModels { public class Services { public object[] inbound { get; set; } public object[] outbound { get; set; } } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive/Models/WellKnownModels/Software.cs b/src/BirdsiteLive/Models/WellKnownModels/Software.cs index 9cbefa6..5a97f05 100644 --- a/src/BirdsiteLive/Models/WellKnownModels/Software.cs +++ b/src/BirdsiteLive/Models/WellKnownModels/Software.cs @@ -1,8 +1,8 @@ -namespace BirdsiteLive.Models.WellKnownModels +namespace BirdsiteLive.Models.WellKnownModels { public class Software { public string name { get; set; } public string version { get; set; } } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive/Models/WellKnownModels/SoftwareV21.cs b/src/BirdsiteLive/Models/WellKnownModels/SoftwareV21.cs index c6fa851..62149b1 100644 --- a/src/BirdsiteLive/Models/WellKnownModels/SoftwareV21.cs +++ b/src/BirdsiteLive/Models/WellKnownModels/SoftwareV21.cs @@ -1,4 +1,4 @@ -namespace BirdsiteLive.Models.WellKnownModels +namespace BirdsiteLive.Models.WellKnownModels { public class SoftwareV21 { @@ -6,4 +6,4 @@ public string repository { get; set; } public string version { get; set; } } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive/Models/WellKnownModels/Usage.cs b/src/BirdsiteLive/Models/WellKnownModels/Usage.cs index 693875f..c9be6c2 100644 --- a/src/BirdsiteLive/Models/WellKnownModels/Usage.cs +++ b/src/BirdsiteLive/Models/WellKnownModels/Usage.cs @@ -1,8 +1,8 @@ -namespace BirdsiteLive.Models.WellKnownModels +namespace BirdsiteLive.Models.WellKnownModels { public class Usage { public int localPosts { get; set; } public Users users { get; set; } } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive/Models/WellKnownModels/Users.cs b/src/BirdsiteLive/Models/WellKnownModels/Users.cs index 3abdb70..de4675a 100644 --- a/src/BirdsiteLive/Models/WellKnownModels/Users.cs +++ b/src/BirdsiteLive/Models/WellKnownModels/Users.cs @@ -1,7 +1,7 @@ -namespace BirdsiteLive.Models.WellKnownModels +namespace BirdsiteLive.Models.WellKnownModels { public class Users { public int total { get; set; } } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive/Models/WellKnownModels/WebFingerLink.cs b/src/BirdsiteLive/Models/WellKnownModels/WebFingerLink.cs index 9945336..e5f16f5 100644 --- a/src/BirdsiteLive/Models/WellKnownModels/WebFingerLink.cs +++ b/src/BirdsiteLive/Models/WellKnownModels/WebFingerLink.cs @@ -1,4 +1,4 @@ -namespace BirdsiteLive.Models.WellKnownModels +namespace BirdsiteLive.Models.WellKnownModels { public class WebFingerLink { @@ -6,4 +6,4 @@ public string type { get; set; } public string href { get; set; } } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive/Models/WellKnownModels/WebFingerResult.cs b/src/BirdsiteLive/Models/WellKnownModels/WebFingerResult.cs index 96c2e84..e388de7 100644 --- a/src/BirdsiteLive/Models/WellKnownModels/WebFingerResult.cs +++ b/src/BirdsiteLive/Models/WellKnownModels/WebFingerResult.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System.Collections.Generic; namespace BirdsiteLive.Models.WellKnownModels { @@ -8,4 +8,4 @@ namespace BirdsiteLive.Models.WellKnownModels public string[] aliases { get; set; } public List links { get; set; } = new List(); } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive/Models/WellKnownModels/WellKnownNodeInfo.cs b/src/BirdsiteLive/Models/WellKnownModels/WellKnownNodeInfo.cs index d34abe6..4a569a0 100644 --- a/src/BirdsiteLive/Models/WellKnownModels/WellKnownNodeInfo.cs +++ b/src/BirdsiteLive/Models/WellKnownModels/WellKnownNodeInfo.cs @@ -1,7 +1,7 @@ -namespace BirdsiteLive.Models.WellKnownModels +namespace BirdsiteLive.Models.WellKnownModels { public class WellKnownNodeInfo { public Link[] links { get; set; } } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive/Program.cs b/src/BirdsiteLive/Program.cs index 04c704f..c5a16f1 100644 --- a/src/BirdsiteLive/Program.cs +++ b/src/BirdsiteLive/Program.cs @@ -1,20 +1,18 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; using BirdsiteLive.Services; + using Lamar.Microsoft.DependencyInjection; + using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; -using Microsoft.Extensions.Logging; namespace BirdsiteLive { public class Program { - public static string VERSION = System.Reflection.Assembly.GetEntryAssembly().GetName().Version.ToString(3) + "+pasture"; + public static string VERSION = + System.Reflection.Assembly.GetEntryAssembly().GetName().Version.ToString(3) + + "+pasture+fishe"; public static void Main(string[] args) { diff --git a/src/BirdsiteLive/Services/AboutPageService.cs b/src/BirdsiteLive/Services/AboutPageService.cs index 8802571..64cb938 100644 --- a/src/BirdsiteLive/Services/AboutPageService.cs +++ b/src/BirdsiteLive/Services/AboutPageService.cs @@ -1,6 +1,7 @@ -using System; +using System; using System.Linq; using System.Threading.Tasks; + using BirdsiteLive.Common.Settings; using BirdsiteLive.DAL.Contracts; using BirdsiteLive.Domain.Repository; @@ -21,7 +22,11 @@ namespace BirdsiteLive.Services private readonly IModerationRepository _moderationRepository; #region Ctor - public AboutPageService(ITwitterUserDal twitterUserDal, InstanceSettings instanceSettings, IModerationRepository moderationRepository) + public AboutPageService( + ITwitterUserDal twitterUserDal, + InstanceSettings instanceSettings, + IModerationRepository moderationRepository + ) { _twitterUserDal = twitterUserDal; _instanceSettings = instanceSettings; @@ -31,8 +36,10 @@ namespace BirdsiteLive.Services public async Task GetAboutPageDataAsync() { - if (_aboutPageData == null || - (DateTime.UtcNow - _aboutPageData.RefreshedTime).TotalMinutes > 15) + if ( + _aboutPageData == null + || (DateTime.UtcNow - _aboutPageData.RefreshedTime).TotalMinutes > 15 + ) { var twitterUserMax = _instanceSettings.MaxUsersCapacity; var twitterUserCount = await _twitterUserDal.GetTwitterUsersCountAsync(); @@ -42,12 +49,24 @@ namespace BirdsiteLive.Services { RefreshedTime = DateTime.UtcNow, Saturation = saturation, - UnlistedUsers = _instanceSettings.UnlistedTwitterAccounts.Length > 0 ? string.Join("\n", _instanceSettings.UnlistedTwitterAccounts.Split(";").Select(i => "
  • " + i + "
  • ")) : "(none)", + UnlistedUsers = + _instanceSettings.UnlistedTwitterAccounts.Length > 0 + ? string.Join( + "\n", + _instanceSettings.UnlistedTwitterAccounts + .Split(";") + .Select(i => "
  • " + i + "
  • ") + ) + : "(none)", Settings = _instanceSettings, ModerationStatus = new ModerationStatus { - Followers = _moderationRepository.GetModerationType(ModerationEntityTypeEnum.Follower), - TwitterAccounts = _moderationRepository.GetModerationType(ModerationEntityTypeEnum.TwitterAccount), + Followers = _moderationRepository.GetModerationType( + ModerationEntityTypeEnum.Follower + ), + TwitterAccounts = _moderationRepository.GetModerationType( + ModerationEntityTypeEnum.TwitterAccount + ), Repository = _moderationRepository } }; @@ -72,4 +91,4 @@ namespace BirdsiteLive.Services public ModerationTypeEnum TwitterAccounts { get; set; } public IModerationRepository Repository { get; set; } } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive/Services/FederationService.cs b/src/BirdsiteLive/Services/FederationService.cs index 0b0faed..95dc344 100644 --- a/src/BirdsiteLive/Services/FederationService.cs +++ b/src/BirdsiteLive/Services/FederationService.cs @@ -1,11 +1,13 @@ -using System; +using System; using System.Linq; using System.Threading; using System.Threading.Tasks; + using BirdsiteLive.DAL; using BirdsiteLive.DAL.Contracts; using BirdsiteLive.Moderation; using BirdsiteLive.Pipeline; + using Microsoft.Extensions.Hosting; namespace BirdsiteLive.Services @@ -18,7 +20,12 @@ namespace BirdsiteLive.Services private readonly IHostApplicationLifetime _applicationLifetime; #region Ctor - public FederationService(IDatabaseInitializer databaseInitializer, IModerationPipeline moderationPipeline, IStatusPublicationPipeline statusPublicationPipeline, IHostApplicationLifetime applicationLifetime) + public FederationService( + IDatabaseInitializer databaseInitializer, + IModerationPipeline moderationPipeline, + IStatusPublicationPipeline statusPublicationPipeline, + IHostApplicationLifetime applicationLifetime + ) { _databaseInitializer = databaseInitializer; _moderationPipeline = moderationPipeline; @@ -42,4 +49,4 @@ namespace BirdsiteLive.Services } } } -} \ No newline at end of file +} diff --git a/src/BirdsiteLive/Startup.cs b/src/BirdsiteLive/Startup.cs index 9758c94..f404d9d 100644 --- a/src/BirdsiteLive/Startup.cs +++ b/src/BirdsiteLive/Startup.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Net.Http; using System.Threading.Tasks; + using BirdsiteLive.Common.Settings; using BirdsiteLive.Common.Structs; using BirdsiteLive.DAL.Contracts; @@ -11,7 +12,9 @@ using BirdsiteLive.DAL.Postgres.Settings; using BirdsiteLive.Models; using BirdsiteLive.Twitter; using BirdsiteLive.Twitter.Tools; + using Lamar; + using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.HttpsPolicy; @@ -30,9 +33,13 @@ namespace BirdsiteLive var builder = new ConfigurationBuilder() .SetBasePath(env.ContentRootPath) .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) - .AddJsonFile($"appsettings.{env.EnvironmentName.ToLowerInvariant()}.json", optional: true) + .AddJsonFile( + $"appsettings.{env.EnvironmentName.ToLowerInvariant()}.json", + optional: true + ) .AddEnvironmentVariables(); - if (env.IsDevelopment()) builder.AddUserSecrets(); + if (env.IsDevelopment()) + builder.AddUserSecrets(); Configuration = builder.Build(); } @@ -42,7 +49,7 @@ namespace BirdsiteLive public void ConfigureServices(IServiceCollection services) { var logsSettings = Configuration.GetSection("Logging").Get(); - if(string.Equals("insights", logsSettings.Type, StringComparison.OrdinalIgnoreCase)) + if (string.Equals("insights", logsSettings.Type, StringComparison.OrdinalIgnoreCase)) { var key = logsSettings.InstrumentationKey; services.AddApplicationInsightsTelemetry(key); @@ -67,18 +74,20 @@ namespace BirdsiteLive var logsSettings = Configuration.GetSection("Logging").Get(); services.For().Use(x => logsSettings); - var moderationSettings = Configuration.GetSection("Moderation").Get(); + var moderationSettings = Configuration + .GetSection("Moderation") + .Get(); services.For().Use(x => moderationSettings); - if (string.Equals(dbSettings.Type, DbTypes.Postgres, StringComparison.OrdinalIgnoreCase)) + if ( + string.Equals(dbSettings.Type, DbTypes.Postgres, StringComparison.OrdinalIgnoreCase) + ) { - var connString = $"Host={dbSettings.Host};Username={dbSettings.User};Password={dbSettings.Password};Database={dbSettings.Name}"; - var postgresSettings = new PostgresSettings - { - ConnString = connString - }; + var connString = + $"Host={dbSettings.Host};Username={dbSettings.User};Password={dbSettings.Password};Database={dbSettings.Name}"; + var postgresSettings = new PostgresSettings { ConnString = connString }; services.For().Use(x => postgresSettings); - + services.For().Use().Singleton(); services.For().Use().Singleton(); services.For().Use().Singleton(); @@ -87,14 +96,17 @@ namespace BirdsiteLive { throw new NotImplementedException($"{dbSettings.Type} is not supported"); } - + services.For().DecorateAllWith(); services.For().Use().Singleton(); services.For().DecorateAllWith(); services.For().Use().Singleton(); - services.For().Use().Singleton(); + services + .For() + .Use() + .Singleton(); services.Scan(_ => { @@ -108,7 +120,7 @@ namespace BirdsiteLive //_.AssemblyContainingType(); //_.Exclude(type => type.Name.Contains("Settings")); - + _.WithDefaultConventions(); _.LookForRegistries(); @@ -140,7 +152,8 @@ namespace BirdsiteLive { endpoints.MapControllerRoute( name: "default", - pattern: "{controller=Home}/{action=Index}/{id?}"); + pattern: "{controller=Home}/{action=Index}/{id?}" + ); }); } } diff --git a/src/BirdsiteLive/Views/Debuging/Index.cshtml b/src/BirdsiteLive/Views/Debuging/Index.cshtml index 5bcde75..fffa611 100644 --- a/src/BirdsiteLive/Views/Debuging/Index.cshtml +++ b/src/BirdsiteLive/Views/Debuging/Index.cshtml @@ -1,4 +1,4 @@ - + @{ ViewData["Title"] = "Index"; } diff --git a/src/BirdsiteLive/Views/Home/Privacy.cshtml b/src/BirdsiteLive/Views/Home/Privacy.cshtml index af4fb19..d01477f 100644 --- a/src/BirdsiteLive/Views/Home/Privacy.cshtml +++ b/src/BirdsiteLive/Views/Home/Privacy.cshtml @@ -1,4 +1,4 @@ -@{ +@{ ViewData["Title"] = "Privacy Policy"; }

    @ViewData["Title"]

    diff --git a/src/BirdsiteLive/Views/Shared/Components/NodeInfo/Default.cshtml b/src/BirdsiteLive/Views/Shared/Components/NodeInfo/Default.cshtml index 4d75949..4406c1a 100644 --- a/src/BirdsiteLive/Views/Shared/Components/NodeInfo/Default.cshtml +++ b/src/BirdsiteLive/Views/Shared/Components/NodeInfo/Default.cshtml @@ -1,4 +1,4 @@ -@model BirdsiteLive.Component.NodeInfoViewModel +@model BirdsiteLive.Component.NodeInfoViewModel
    @if (ViewData.Model.DiscloseRestrictions && (ViewData.Model.WhitelistingEnabled || ViewData.Model.BlacklistingEnabled)) diff --git a/src/BirdsiteLive/Views/Shared/Error.cshtml b/src/BirdsiteLive/Views/Shared/Error.cshtml index a1e0478..0c47bb0 100644 --- a/src/BirdsiteLive/Views/Shared/Error.cshtml +++ b/src/BirdsiteLive/Views/Shared/Error.cshtml @@ -1,4 +1,4 @@ -@model ErrorViewModel +@model ErrorViewModel @{ ViewData["Title"] = "Error"; } diff --git a/src/BirdsiteLive/Views/Shared/_Layout.cshtml b/src/BirdsiteLive/Views/Shared/_Layout.cshtml index bfcdc77..c4b5ed6 100644 --- a/src/BirdsiteLive/Views/Shared/_Layout.cshtml +++ b/src/BirdsiteLive/Views/Shared/_Layout.cshtml @@ -1,4 +1,4 @@ -@using Microsoft.Extensions.Configuration +@using Microsoft.Extensions.Configuration @inject IConfiguration Configuration diff --git a/src/BirdsiteLive/Views/Shared/_ValidationScriptsPartial.cshtml b/src/BirdsiteLive/Views/Shared/_ValidationScriptsPartial.cshtml index 5a16d80..7d8dd3e 100644 --- a/src/BirdsiteLive/Views/Shared/_ValidationScriptsPartial.cshtml +++ b/src/BirdsiteLive/Views/Shared/_ValidationScriptsPartial.cshtml @@ -1,2 +1,2 @@ - + diff --git a/src/BirdsiteLive/Views/Statistics/Index.cshtml b/src/BirdsiteLive/Views/Statistics/Index.cshtml index 4382e2a..882bc75 100644 --- a/src/BirdsiteLive/Views/Statistics/Index.cshtml +++ b/src/BirdsiteLive/Views/Statistics/Index.cshtml @@ -1,4 +1,4 @@ -@model BirdsiteLive.Models.StatisticsModels.Statistics +@model BirdsiteLive.Models.StatisticsModels.Statistics @{ ViewBag.Title = "Statistics"; diff --git a/src/BirdsiteLive/Views/Users/Index.cshtml b/src/BirdsiteLive/Views/Users/Index.cshtml index f3812cc..0169f62 100644 --- a/src/BirdsiteLive/Views/Users/Index.cshtml +++ b/src/BirdsiteLive/Views/Users/Index.cshtml @@ -1,4 +1,4 @@ -@using Tweetinvi.Streams.Model.AccountActivity +@using Tweetinvi.Streams.Model.AccountActivity @model DisplayTwitterUser @{ ViewData["Title"] = "User"; diff --git a/src/BirdsiteLive/Views/Users/Tweet.cshtml b/src/BirdsiteLive/Views/Users/Tweet.cshtml index a1aa7fe..937fd70 100644 --- a/src/BirdsiteLive/Views/Users/Tweet.cshtml +++ b/src/BirdsiteLive/Views/Users/Tweet.cshtml @@ -1,4 +1,4 @@ -@{ +@{ ViewData["Title"] = "Tweet"; } diff --git a/src/BirdsiteLive/Views/Users/UserNotFound.cshtml b/src/BirdsiteLive/Views/Users/UserNotFound.cshtml index ec0928f..6fd78b2 100644 --- a/src/BirdsiteLive/Views/Users/UserNotFound.cshtml +++ b/src/BirdsiteLive/Views/Users/UserNotFound.cshtml @@ -1,4 +1,4 @@ -@{ +@{ ViewData["Title"] = "User"; } diff --git a/src/BirdsiteLive/Views/_ViewImports.cshtml b/src/BirdsiteLive/Views/_ViewImports.cshtml index 5b552ac..6e23fce 100644 --- a/src/BirdsiteLive/Views/_ViewImports.cshtml +++ b/src/BirdsiteLive/Views/_ViewImports.cshtml @@ -1,3 +1,3 @@ -@using BirdsiteLive +@using BirdsiteLive @using BirdsiteLive.Models @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers diff --git a/src/BirdsiteLive/Views/_ViewStart.cshtml b/src/BirdsiteLive/Views/_ViewStart.cshtml index a5f1004..820a2f6 100644 --- a/src/BirdsiteLive/Views/_ViewStart.cshtml +++ b/src/BirdsiteLive/Views/_ViewStart.cshtml @@ -1,3 +1,3 @@ -@{ +@{ Layout = "_Layout"; } diff --git a/src/BirdsiteLive/wwwroot/css/birdsite.css b/src/BirdsiteLive/wwwroot/css/birdsite.css index 5b6023c..d471a1d 100644 --- a/src/BirdsiteLive/wwwroot/css/birdsite.css +++ b/src/BirdsiteLive/wwwroot/css/birdsite.css @@ -1,4 +1,4 @@ -.nounderline { +.nounderline { text-decoration: none !important } diff --git a/src/BirdsiteLive/wwwroot/css/pattern.css b/src/BirdsiteLive/wwwroot/css/pattern.css index 5cd3d60..75955f6 100644 --- a/src/BirdsiteLive/wwwroot/css/pattern.css +++ b/src/BirdsiteLive/wwwroot/css/pattern.css @@ -1,4 +1,4 @@ -.container-nodeinfo { +.container-nodeinfo { line-height: 30px; text-align: center; } diff --git a/src/BirdsiteLive/wwwroot/css/site.css b/src/BirdsiteLive/wwwroot/css/site.css index e679a8e..f541d8f 100644 --- a/src/BirdsiteLive/wwwroot/css/site.css +++ b/src/BirdsiteLive/wwwroot/css/site.css @@ -1,4 +1,4 @@ -/* Please see documentation at https://docs.microsoft.com/aspnet/core/client-side/bundling-and-minification +/* Please see documentation at https://docs.microsoft.com/aspnet/core/client-side/bundling-and-minification for details on configuring this project to bundle and minify static web assets. */ a.navbar-brand { diff --git a/src/BirdsiteLive/wwwroot/js/site.js b/src/BirdsiteLive/wwwroot/js/site.js index ac49c18..f5d74f4 100644 --- a/src/BirdsiteLive/wwwroot/js/site.js +++ b/src/BirdsiteLive/wwwroot/js/site.js @@ -1,4 +1,4 @@ -// Please see documentation at https://docs.microsoft.com/aspnet/core/client-side/bundling-and-minification +// Please see documentation at https://docs.microsoft.com/aspnet/core/client-side/bundling-and-minification // for details on configuring this project to bundle and minify static web assets. // Write your JavaScript code. diff --git a/src/DataAccessLayers/BirdsiteLive.DAL.Postgres/BirdsiteLive.DAL.Postgres.csproj b/src/DataAccessLayers/BirdsiteLive.DAL.Postgres/BirdsiteLive.DAL.Postgres.csproj index 690c878..a1d19fe 100644 --- a/src/DataAccessLayers/BirdsiteLive.DAL.Postgres/BirdsiteLive.DAL.Postgres.csproj +++ b/src/DataAccessLayers/BirdsiteLive.DAL.Postgres/BirdsiteLive.DAL.Postgres.csproj @@ -1,7 +1,7 @@ - + - netstandard2.0 + net6.0 diff --git a/src/DataAccessLayers/BirdsiteLive.DAL.Postgres/DataAccessLayers/Base/PostgresBase.cs b/src/DataAccessLayers/BirdsiteLive.DAL.Postgres/DataAccessLayers/Base/PostgresBase.cs index 1c59387..64e107e 100644 --- a/src/DataAccessLayers/BirdsiteLive.DAL.Postgres/DataAccessLayers/Base/PostgresBase.cs +++ b/src/DataAccessLayers/BirdsiteLive.DAL.Postgres/DataAccessLayers/Base/PostgresBase.cs @@ -1,4 +1,5 @@ -using BirdsiteLive.DAL.Postgres.Settings; +using BirdsiteLive.DAL.Postgres.Settings; + using Npgsql; namespace BirdsiteLive.DAL.Postgres.DataAccessLayers.Base @@ -16,10 +17,7 @@ namespace BirdsiteLive.DAL.Postgres.DataAccessLayers.Base protected NpgsqlConnection Connection { - get - { - return new NpgsqlConnection(_settings.ConnString); - } + get { return new NpgsqlConnection(_settings.ConnString); } } } -} \ No newline at end of file +} diff --git a/src/DataAccessLayers/BirdsiteLive.DAL.Postgres/DataAccessLayers/CachedTweetsPostgresDal.cs b/src/DataAccessLayers/BirdsiteLive.DAL.Postgres/DataAccessLayers/CachedTweetsPostgresDal.cs index b95d5d1..869dd07 100644 --- a/src/DataAccessLayers/BirdsiteLive.DAL.Postgres/DataAccessLayers/CachedTweetsPostgresDal.cs +++ b/src/DataAccessLayers/BirdsiteLive.DAL.Postgres/DataAccessLayers/CachedTweetsPostgresDal.cs @@ -1,13 +1,17 @@ -using System; +using System; using System.Linq; using System.Threading.Tasks; + using BirdsiteLive.DAL.Contracts; using BirdsiteLive.DAL.Models; using BirdsiteLive.DAL.Postgres.DataAccessLayers.Base; using BirdsiteLive.DAL.Postgres.Settings; using BirdsiteLive.DAL.Postgres.Tools; + using Dapper; + using Newtonsoft.Json; + using Tweetinvi.Models; namespace BirdsiteLive.DAL.Postgres.DataAccessLayers @@ -15,16 +19,15 @@ namespace BirdsiteLive.DAL.Postgres.DataAccessLayers public class CachedTweetsPostgresDal : PostgresBase, ICachedTweetsDal { #region Ctor - public CachedTweetsPostgresDal(PostgresSettings settings) : base(settings) - { - - } + public CachedTweetsPostgresDal(PostgresSettings settings) : base(settings) { } #endregion public async Task CreateTweetAsync(long tweetId, int userId, CachedTweet tweet) { - if(tweetId == default) throw new ArgumentException("tweetId"); - if(userId == default) throw new ArgumentException("userId"); + if (tweetId == default) + throw new ArgumentException("tweetId"); + if (userId == default) + throw new ArgumentException("userId"); var serializedData = JsonConvert.SerializeObject(tweet); @@ -34,13 +37,15 @@ namespace BirdsiteLive.DAL.Postgres.DataAccessLayers await dbConnection.ExecuteAsync( $"INSERT INTO {_settings.CachedTweetsTableName} (id,twitterUserId,data) VALUES(@id,@twitterUserId,CAST(@data as json))", - new { id = tweetId, twitterUserId = userId, data = serializedData }); + new { id = tweetId, twitterUserId = userId, data = serializedData } + ); } } public async Task GetTweetAsync(long tweetId) { - if (tweetId == default) throw new ArgumentException("tweetId"); + if (tweetId == default) + throw new ArgumentException("tweetId"); var query = $"SELECT * FROM {_settings.CachedTweetsTableName} WHERE id = @id"; @@ -48,14 +53,17 @@ namespace BirdsiteLive.DAL.Postgres.DataAccessLayers { dbConnection.Open(); - var result = (await dbConnection.QueryAsync(query, new { id = tweetId })).FirstOrDefault(); + var result = ( + await dbConnection.QueryAsync(query, new { id = tweetId }) + ).FirstOrDefault(); return Convert(result); } } public async Task DeleteTweetAsync(long tweetId) { - if (tweetId == default) throw new ArgumentException("tweetId"); + if (tweetId == default) + throw new ArgumentException("tweetId"); var query = $"DELETE FROM {_settings.CachedTweetsTableName} WHERE id = @id"; @@ -69,7 +77,8 @@ namespace BirdsiteLive.DAL.Postgres.DataAccessLayers private CachedTweet Convert(SerializedTweet result) { - if (result == null || string.IsNullOrWhiteSpace(result.Data)) return null; + if (result == null || string.IsNullOrWhiteSpace(result.Data)) + return null; return JsonConvert.DeserializeObject(result.Data); } } @@ -80,4 +89,4 @@ namespace BirdsiteLive.DAL.Postgres.DataAccessLayers public int TwitterUserId { get; set; } public string Data { get; set; } } -} \ No newline at end of file +} diff --git a/src/DataAccessLayers/BirdsiteLive.DAL.Postgres/DataAccessLayers/DbInitializerPostgresDal.cs b/src/DataAccessLayers/BirdsiteLive.DAL.Postgres/DataAccessLayers/DbInitializerPostgresDal.cs index 2e3acea..7cf9ead 100644 --- a/src/DataAccessLayers/BirdsiteLive.DAL.Postgres/DataAccessLayers/DbInitializerPostgresDal.cs +++ b/src/DataAccessLayers/BirdsiteLive.DAL.Postgres/DataAccessLayers/DbInitializerPostgresDal.cs @@ -1,14 +1,17 @@ -using System; +using System; using System.Data; using System.Linq; using System.Runtime.CompilerServices; using System.Threading.Tasks; using System.Xml; + using BirdsiteLive.DAL.Contracts; using BirdsiteLive.DAL.Postgres.DataAccessLayers.Base; using BirdsiteLive.DAL.Postgres.Settings; using BirdsiteLive.DAL.Postgres.Tools; + using Dapper; + using Npgsql; namespace BirdsiteLive.DAL.Postgres.DataAccessLayers @@ -27,7 +30,8 @@ namespace BirdsiteLive.DAL.Postgres.DataAccessLayers private const string DbVersionType = "db-version"; #region Ctor - public DbInitializerPostgresDal(PostgresSettings settings, PostgresTools tools) : base(settings) + public DbInitializerPostgresDal(PostgresSettings settings, PostgresTools tools) + : base(settings) { _tools = tools; } @@ -43,7 +47,12 @@ namespace BirdsiteLive.DAL.Postgres.DataAccessLayers { dbConnection.Open(); - var result = (await dbConnection.QueryAsync(query, new { type = DbVersionType })).FirstOrDefault(); + var result = ( + await dbConnection.QueryAsync( + query, + new { type = DbVersionType } + ) + ).FirstOrDefault(); if (result == default) return null; @@ -67,8 +76,9 @@ namespace BirdsiteLive.DAL.Postgres.DataAccessLayers public async Task InitDbAsync() { - // Create version table - var createVersion = $@"CREATE TABLE {_settings.DbVersionTableName} + // Create version table + var createVersion = + $@"CREATE TABLE {_settings.DbVersionTableName} ( type VARCHAR(128) PRIMARY KEY, @@ -78,7 +88,8 @@ namespace BirdsiteLive.DAL.Postgres.DataAccessLayers await _tools.ExecuteRequestAsync(createVersion); // Create Twitter User table - var createTwitter = $@"CREATE TABLE {_settings.TwitterUserTableName} + var createTwitter = + $@"CREATE TABLE {_settings.TwitterUserTableName} ( id SERIAL PRIMARY KEY, acct VARCHAR(20) UNIQUE, @@ -89,7 +100,8 @@ namespace BirdsiteLive.DAL.Postgres.DataAccessLayers await _tools.ExecuteRequestAsync(createTwitter); // Create Followers table - var createFollowers = $@"CREATE TABLE {_settings.FollowersTableName} + var createFollowers = + $@"CREATE TABLE {_settings.FollowersTableName} ( id SERIAL PRIMARY KEY, @@ -104,8 +116,9 @@ namespace BirdsiteLive.DAL.Postgres.DataAccessLayers );"; await _tools.ExecuteRequestAsync(createFollowers); - // Create Cached Tweet table - var createCachedTweets = $@"CREATE TABLE {_settings.CachedTweetsTableName} + // Create Cached Tweet table + var createCachedTweets = + $@"CREATE TABLE {_settings.CachedTweetsTableName} ( id BIGINT PRIMARY KEY, twitterUserId INTEGER, @@ -121,7 +134,13 @@ namespace BirdsiteLive.DAL.Postgres.DataAccessLayers await dbConnection.ExecuteAsync( $"INSERT INTO {_settings.DbVersionTableName} (type,major,minor) VALUES(@type,@major,@minor)", - new { type = DbVersionType, major = firstVersion.Major, minor = firstVersion.Minor }); + new + { + type = DbVersionType, + major = firstVersion.Major, + minor = firstVersion.Minor + } + ); } return firstVersion; @@ -131,10 +150,10 @@ namespace BirdsiteLive.DAL.Postgres.DataAccessLayers { return new[] { - new Tuple(new Version(1,0), new Version(2,0)), - new Tuple(new Version(2,0), new Version(2,1)), - new Tuple(new Version(2,1), new Version(2,2)), - new Tuple(new Version(2,2), new Version(2,3)) + new Tuple(new Version(1, 0), new Version(2, 0)), + new Tuple(new Version(2, 0), new Version(2, 1)), + new Tuple(new Version(2, 1), new Version(2, 2)), + new Tuple(new Version(2, 2), new Version(2, 3)) }; } @@ -142,25 +161,30 @@ namespace BirdsiteLive.DAL.Postgres.DataAccessLayers { if (from == new Version(1, 0) && to == new Version(2, 0)) { - var addLastSync = $@"ALTER TABLE {_settings.TwitterUserTableName} ADD lastSync TIMESTAMP (2) WITHOUT TIME ZONE"; + var addLastSync = + $@"ALTER TABLE {_settings.TwitterUserTableName} ADD lastSync TIMESTAMP (2) WITHOUT TIME ZONE"; await _tools.ExecuteRequestAsync(addLastSync); - var addIndex = $@"CREATE INDEX IF NOT EXISTS lastsync_twitteruser ON {_settings.TwitterUserTableName}(lastSync)"; + var addIndex = + $@"CREATE INDEX IF NOT EXISTS lastsync_twitteruser ON {_settings.TwitterUserTableName}(lastSync)"; await _tools.ExecuteRequestAsync(addIndex); } else if (from == new Version(2, 0) && to == new Version(2, 1)) { - var addActorId = $@"ALTER TABLE {_settings.FollowersTableName} ADD actorId VARCHAR(2048)"; + var addActorId = + $@"ALTER TABLE {_settings.FollowersTableName} ADD actorId VARCHAR(2048)"; await _tools.ExecuteRequestAsync(addActorId); } else if (from == new Version(2, 1) && to == new Version(2, 2)) { - var addLastSync = $@"ALTER TABLE {_settings.TwitterUserTableName} ADD fetchingErrorCount SMALLINT"; + var addLastSync = + $@"ALTER TABLE {_settings.TwitterUserTableName} ADD fetchingErrorCount SMALLINT"; await _tools.ExecuteRequestAsync(addLastSync); } else if (from == new Version(2, 2) && to == new Version(2, 3)) { - var addPostingError = $@"ALTER TABLE {_settings.FollowersTableName} ADD postingErrorCount SMALLINT"; + var addPostingError = + $@"ALTER TABLE {_settings.FollowersTableName} ADD postingErrorCount SMALLINT"; await _tools.ExecuteRequestAsync(addPostingError); } else @@ -180,7 +204,8 @@ namespace BirdsiteLive.DAL.Postgres.DataAccessLayers await dbConnection.ExecuteAsync( $"UPDATE {_settings.DbVersionTableName} SET major = @major, minor = @minor WHERE type = @type", - new { type = DbVersionType, major = newVersion.Major, minor = newVersion.Minor }); + new { type = DbVersionType, major = newVersion.Major, minor = newVersion.Minor } + ); } } @@ -200,4 +225,4 @@ namespace BirdsiteLive.DAL.Postgres.DataAccessLayers } } } -} \ No newline at end of file +} diff --git a/src/DataAccessLayers/BirdsiteLive.DAL.Postgres/DataAccessLayers/FollowersPostgresDal.cs b/src/DataAccessLayers/BirdsiteLive.DAL.Postgres/DataAccessLayers/FollowersPostgresDal.cs index db2f9f7..4aa4cfb 100644 --- a/src/DataAccessLayers/BirdsiteLive.DAL.Postgres/DataAccessLayers/FollowersPostgresDal.cs +++ b/src/DataAccessLayers/BirdsiteLive.DAL.Postgres/DataAccessLayers/FollowersPostgresDal.cs @@ -1,12 +1,15 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; + using BirdsiteLive.DAL.Contracts; using BirdsiteLive.DAL.Models; using BirdsiteLive.DAL.Postgres.DataAccessLayers.Base; using BirdsiteLive.DAL.Postgres.Settings; + using Dapper; + using Newtonsoft.Json; namespace BirdsiteLive.DAL.Postgres.DataAccessLayers @@ -14,16 +17,23 @@ namespace BirdsiteLive.DAL.Postgres.DataAccessLayers public class FollowersPostgresDal : PostgresBase, IFollowersDal { #region Ctor - public FollowersPostgresDal(PostgresSettings settings) : base(settings) - { - - } + public FollowersPostgresDal(PostgresSettings settings) : base(settings) { } #endregion - public async Task CreateFollowerAsync(string acct, string host, string inboxRoute, string sharedInboxRoute, string actorId, int[] followings = null, Dictionary followingSyncStatus = null) + public async Task CreateFollowerAsync( + string acct, + string host, + string inboxRoute, + string sharedInboxRoute, + string actorId, + int[] followings = null, + Dictionary followingSyncStatus = null + ) { - if(followings == null) followings = new int[0]; - if(followingSyncStatus == null) followingSyncStatus = new Dictionary(); + if (followings == null) + followings = new int[0]; + if (followingSyncStatus == null) + followingSyncStatus = new Dictionary(); var serializedDic = JsonConvert.SerializeObject(followingSyncStatus); @@ -36,7 +46,17 @@ namespace BirdsiteLive.DAL.Postgres.DataAccessLayers await dbConnection.ExecuteAsync( $"INSERT INTO {_settings.FollowersTableName} (acct,host,inboxRoute,sharedInboxRoute,followings,followingsSyncStatus,actorId) VALUES(@acct,@host,@inboxRoute,@sharedInboxRoute,@followings,CAST(@followingsSyncStatus as json),@actorId)", - new { acct, host, inboxRoute, sharedInboxRoute, followings, followingsSyncStatus = serializedDic, actorId }); + new + { + acct, + host, + inboxRoute, + sharedInboxRoute, + followings, + followingsSyncStatus = serializedDic, + actorId + } + ); } } @@ -55,7 +75,8 @@ namespace BirdsiteLive.DAL.Postgres.DataAccessLayers public async Task GetFailingFollowersCountAsync() { - var query = $"SELECT COUNT(*) FROM {_settings.FollowersTableName} WHERE postingErrorCount > 0"; + var query = + $"SELECT COUNT(*) FROM {_settings.FollowersTableName} WHERE postingErrorCount > 0"; using (var dbConnection = Connection) { @@ -68,7 +89,8 @@ namespace BirdsiteLive.DAL.Postgres.DataAccessLayers public async Task GetFollowerAsync(string acct, string host) { - var query = $"SELECT * FROM {_settings.FollowersTableName} WHERE acct = @acct AND host = @host"; + var query = + $"SELECT * FROM {_settings.FollowersTableName} WHERE acct = @acct AND host = @host"; acct = acct.ToLowerInvariant(); host = host.ToLowerInvariant(); @@ -77,22 +99,28 @@ namespace BirdsiteLive.DAL.Postgres.DataAccessLayers { dbConnection.Open(); - var result = (await dbConnection.QueryAsync(query, new { acct, host })).FirstOrDefault(); + var result = ( + await dbConnection.QueryAsync(query, new { acct, host }) + ).FirstOrDefault(); return Convert(result); } } public async Task GetFollowersAsync(int followedUserId) { - if (followedUserId == default) throw new ArgumentException("followedUserId"); + if (followedUserId == default) + throw new ArgumentException("followedUserId"); var query = $"SELECT * FROM {_settings.FollowersTableName} WHERE @id=ANY(followings)"; - + using (var dbConnection = Connection) { dbConnection.Open(); - var result = await dbConnection.QueryAsync(query, new { id = followedUserId}); + var result = await dbConnection.QueryAsync( + query, + new { id = followedUserId } + ); return result.Select(Convert).ToArray(); } } @@ -112,24 +140,37 @@ namespace BirdsiteLive.DAL.Postgres.DataAccessLayers public async Task UpdateFollowerAsync(Follower follower) { - if (follower == default) throw new ArgumentException("follower"); - if (follower.Id == default) throw new ArgumentException("id"); + if (follower == default) + throw new ArgumentException("follower"); + if (follower.Id == default) + throw new ArgumentException("id"); var serializedDic = JsonConvert.SerializeObject(follower.FollowingsSyncStatus); - var query = $"UPDATE {_settings.FollowersTableName} SET followings = @followings, followingsSyncStatus = CAST(@followingsSyncStatus as json), postingErrorCount = @postingErrorCount WHERE id = @id"; + var query = + $"UPDATE {_settings.FollowersTableName} SET followings = @followings, followingsSyncStatus = CAST(@followingsSyncStatus as json), postingErrorCount = @postingErrorCount WHERE id = @id"; using (var dbConnection = Connection) { dbConnection.Open(); - await dbConnection.QueryAsync(query, new { follower.Id, follower.Followings, followingsSyncStatus = serializedDic, postingErrorCount = follower.PostingErrorCount }); + await dbConnection.QueryAsync( + query, + new + { + follower.Id, + follower.Followings, + followingsSyncStatus = serializedDic, + postingErrorCount = follower.PostingErrorCount + } + ); } } public async Task DeleteFollowerAsync(int id) { - if (id == default) throw new ArgumentException("id"); - + if (id == default) + throw new ArgumentException("id"); + var query = $"DELETE FROM {_settings.FollowersTableName} WHERE id = @id"; using (var dbConnection = Connection) @@ -142,13 +183,16 @@ namespace BirdsiteLive.DAL.Postgres.DataAccessLayers public async Task DeleteFollowerAsync(string acct, string host) { - if (string.IsNullOrWhiteSpace(acct)) throw new ArgumentException("acct"); - if (string.IsNullOrWhiteSpace(host)) throw new ArgumentException("host"); + if (string.IsNullOrWhiteSpace(acct)) + throw new ArgumentException("acct"); + if (string.IsNullOrWhiteSpace(host)) + throw new ArgumentException("host"); acct = acct.ToLowerInvariant(); host = host.ToLowerInvariant(); - var query = $"DELETE FROM {_settings.FollowersTableName} WHERE acct = @acct AND host = @host"; + var query = + $"DELETE FROM {_settings.FollowersTableName} WHERE acct = @acct AND host = @host"; using (var dbConnection = Connection) { @@ -160,7 +204,8 @@ namespace BirdsiteLive.DAL.Postgres.DataAccessLayers private Follower Convert(SerializedFollower follower) { - if (follower == null) return null; + if (follower == null) + return null; return new Follower() { @@ -171,13 +216,16 @@ namespace BirdsiteLive.DAL.Postgres.DataAccessLayers ActorId = follower.ActorId, SharedInboxRoute = follower.SharedInboxRoute, Followings = follower.Followings.ToList(), - FollowingsSyncStatus = JsonConvert.DeserializeObject>(follower.FollowingsSyncStatus), + FollowingsSyncStatus = JsonConvert.DeserializeObject>( + follower.FollowingsSyncStatus + ), PostingErrorCount = follower.PostingErrorCount }; } } - internal class SerializedFollower { + internal class SerializedFollower + { public int Id { get; set; } public int[] Followings { get; set; } @@ -190,4 +238,4 @@ namespace BirdsiteLive.DAL.Postgres.DataAccessLayers public string ActorId { get; set; } public int PostingErrorCount { get; set; } } -} \ No newline at end of file +} diff --git a/src/DataAccessLayers/BirdsiteLive.DAL.Postgres/DataAccessLayers/TwitterUserPostgresDal.cs b/src/DataAccessLayers/BirdsiteLive.DAL.Postgres/DataAccessLayers/TwitterUserPostgresDal.cs index 11214d4..214f341 100644 --- a/src/DataAccessLayers/BirdsiteLive.DAL.Postgres/DataAccessLayers/TwitterUserPostgresDal.cs +++ b/src/DataAccessLayers/BirdsiteLive.DAL.Postgres/DataAccessLayers/TwitterUserPostgresDal.cs @@ -1,10 +1,12 @@ -using System; +using System; using System.Linq; using System.Threading.Tasks; + using BirdsiteLive.DAL.Contracts; using BirdsiteLive.DAL.Models; using BirdsiteLive.DAL.Postgres.DataAccessLayers.Base; using BirdsiteLive.DAL.Postgres.Settings; + using Dapper; namespace BirdsiteLive.DAL.Postgres.DataAccessLayers @@ -12,10 +14,7 @@ namespace BirdsiteLive.DAL.Postgres.DataAccessLayers public class TwitterUserPostgresDal : PostgresBase, ITwitterUserDal { #region Ctor - public TwitterUserPostgresDal(PostgresSettings settings) : base(settings) - { - - } + public TwitterUserPostgresDal(PostgresSettings settings) : base(settings) { } #endregion public async Task CreateTwitterUserAsync(string acct, long lastTweetPostedId) @@ -28,7 +27,13 @@ namespace BirdsiteLive.DAL.Postgres.DataAccessLayers await dbConnection.ExecuteAsync( $"INSERT INTO {_settings.TwitterUserTableName} (acct,lastTweetPostedId,lastTweetSynchronizedForAllFollowersId) VALUES(@acct,@lastTweetPostedId,@lastTweetSynchronizedForAllFollowersId)", - new { acct, lastTweetPostedId, lastTweetSynchronizedForAllFollowersId = lastTweetPostedId }); + new + { + acct, + lastTweetPostedId, + lastTweetSynchronizedForAllFollowersId = lastTweetPostedId + } + ); } } @@ -42,7 +47,9 @@ namespace BirdsiteLive.DAL.Postgres.DataAccessLayers { dbConnection.Open(); - var result = (await dbConnection.QueryAsync(query, new { acct })).FirstOrDefault(); + var result = ( + await dbConnection.QueryAsync(query, new { acct }) + ).FirstOrDefault(); return result; } } @@ -50,12 +57,14 @@ namespace BirdsiteLive.DAL.Postgres.DataAccessLayers public async Task GetTwitterUserAsync(int id) { var query = $"SELECT * FROM {_settings.TwitterUserTableName} WHERE id = @id"; - + using (var dbConnection = Connection) { dbConnection.Open(); - var result = (await dbConnection.QueryAsync(query, new { id })).FirstOrDefault(); + var result = ( + await dbConnection.QueryAsync(query, new { id }) + ).FirstOrDefault(); return result; } } @@ -75,7 +84,8 @@ namespace BirdsiteLive.DAL.Postgres.DataAccessLayers public async Task GetFailingTwitterUsersCountAsync() { - var query = $"SELECT COUNT(*) FROM {_settings.TwitterUserTableName} WHERE fetchingErrorCount > 0"; + var query = + $"SELECT COUNT(*) FROM {_settings.TwitterUserTableName} WHERE fetchingErrorCount > 0"; using (var dbConnection = Connection) { @@ -88,13 +98,17 @@ namespace BirdsiteLive.DAL.Postgres.DataAccessLayers public async Task GetAllTwitterUsersAsync(int maxNumber) { - var query = $"SELECT * FROM {_settings.TwitterUserTableName} ORDER BY lastSync ASC NULLS FIRST LIMIT @maxNumber"; + var query = + $"SELECT * FROM {_settings.TwitterUserTableName} ORDER BY lastSync ASC NULLS FIRST LIMIT @maxNumber"; using (var dbConnection = Connection) { dbConnection.Open(); - var result = await dbConnection.QueryAsync(query, new { maxNumber }); + var result = await dbConnection.QueryAsync( + query, + new { maxNumber } + ); return result.ToArray(); } } @@ -112,31 +126,59 @@ namespace BirdsiteLive.DAL.Postgres.DataAccessLayers } } - public async Task UpdateTwitterUserAsync(int id, long lastTweetPostedId, long lastTweetSynchronizedForAllFollowersId, int fetchingErrorCount, DateTime lastSync) + public async Task UpdateTwitterUserAsync( + int id, + long lastTweetPostedId, + long lastTweetSynchronizedForAllFollowersId, + int fetchingErrorCount, + DateTime lastSync + ) { - if(id == default) throw new ArgumentException("id"); - if(lastTweetPostedId == default) throw new ArgumentException("lastTweetPostedId"); - if(lastTweetSynchronizedForAllFollowersId == default) throw new ArgumentException("lastTweetSynchronizedForAllFollowersId"); - if(lastSync == default) throw new ArgumentException("lastSync"); + if (id == default) + throw new ArgumentException("id"); + if (lastTweetPostedId == default) + throw new ArgumentException("lastTweetPostedId"); + if (lastTweetSynchronizedForAllFollowersId == default) + throw new ArgumentException("lastTweetSynchronizedForAllFollowersId"); + if (lastSync == default) + throw new ArgumentException("lastSync"); - var query = $"UPDATE {_settings.TwitterUserTableName} SET lastTweetPostedId = @lastTweetPostedId, lastTweetSynchronizedForAllFollowersId = @lastTweetSynchronizedForAllFollowersId, fetchingErrorCount = @fetchingErrorCount, lastSync = @lastSync WHERE id = @id"; + var query = + $"UPDATE {_settings.TwitterUserTableName} SET lastTweetPostedId = @lastTweetPostedId, lastTweetSynchronizedForAllFollowersId = @lastTweetSynchronizedForAllFollowersId, fetchingErrorCount = @fetchingErrorCount, lastSync = @lastSync WHERE id = @id"; using (var dbConnection = Connection) { dbConnection.Open(); - await dbConnection.QueryAsync(query, new { id, lastTweetPostedId, lastTweetSynchronizedForAllFollowersId, fetchingErrorCount, lastSync = lastSync.ToUniversalTime() }); + await dbConnection.QueryAsync( + query, + new + { + id, + lastTweetPostedId, + lastTweetSynchronizedForAllFollowersId, + fetchingErrorCount, + lastSync = lastSync.ToUniversalTime() + } + ); } } public async Task UpdateTwitterUserAsync(SyncTwitterUser user) { - await UpdateTwitterUserAsync(user.Id, user.LastTweetPostedId, user.LastTweetSynchronizedForAllFollowersId, user.FetchingErrorCount, user.LastSync); + await UpdateTwitterUserAsync( + user.Id, + user.LastTweetPostedId, + user.LastTweetSynchronizedForAllFollowersId, + user.FetchingErrorCount, + user.LastSync + ); } public async Task DeleteTwitterUserAsync(string acct) { - if (string.IsNullOrWhiteSpace(acct)) throw new ArgumentException("acct"); + if (string.IsNullOrWhiteSpace(acct)) + throw new ArgumentException("acct"); acct = acct.ToLowerInvariant(); @@ -152,8 +194,9 @@ namespace BirdsiteLive.DAL.Postgres.DataAccessLayers public async Task DeleteTwitterUserAsync(int id) { - if (id == default) throw new ArgumentException("id"); - + if (id == default) + throw new ArgumentException("id"); + var query = $"DELETE FROM {_settings.TwitterUserTableName} WHERE id = @id"; using (var dbConnection = Connection) @@ -164,4 +207,4 @@ namespace BirdsiteLive.DAL.Postgres.DataAccessLayers } } } -} \ No newline at end of file +} diff --git a/src/DataAccessLayers/BirdsiteLive.DAL.Postgres/Settings/PostgresSettings.cs b/src/DataAccessLayers/BirdsiteLive.DAL.Postgres/Settings/PostgresSettings.cs index c7504ef..211ba90 100644 --- a/src/DataAccessLayers/BirdsiteLive.DAL.Postgres/Settings/PostgresSettings.cs +++ b/src/DataAccessLayers/BirdsiteLive.DAL.Postgres/Settings/PostgresSettings.cs @@ -1,4 +1,4 @@ -namespace BirdsiteLive.DAL.Postgres.Settings +namespace BirdsiteLive.DAL.Postgres.Settings { public class PostgresSettings { @@ -9,4 +9,4 @@ public string FollowersTableName { get; set; } = "followers"; public string CachedTweetsTableName { get; set; } = "cached_tweets"; } -} \ No newline at end of file +} diff --git a/src/DataAccessLayers/BirdsiteLive.DAL.Postgres/Tools/PostgresTools.cs b/src/DataAccessLayers/BirdsiteLive.DAL.Postgres/Tools/PostgresTools.cs index 32a379f..7446c02 100644 --- a/src/DataAccessLayers/BirdsiteLive.DAL.Postgres/Tools/PostgresTools.cs +++ b/src/DataAccessLayers/BirdsiteLive.DAL.Postgres/Tools/PostgresTools.cs @@ -1,6 +1,8 @@ -using System; +using System; using System.Threading.Tasks; + using BirdsiteLive.DAL.Postgres.Settings; + using Npgsql; namespace BirdsiteLive.DAL.Postgres.Tools @@ -26,4 +28,4 @@ namespace BirdsiteLive.DAL.Postgres.Tools } } } -} \ No newline at end of file +} diff --git a/src/DataAccessLayers/BirdsiteLive.DAL/BirdsiteLive.DAL.csproj b/src/DataAccessLayers/BirdsiteLive.DAL/BirdsiteLive.DAL.csproj index 84e0bf0..847e55f 100644 --- a/src/DataAccessLayers/BirdsiteLive.DAL/BirdsiteLive.DAL.csproj +++ b/src/DataAccessLayers/BirdsiteLive.DAL/BirdsiteLive.DAL.csproj @@ -1,7 +1,7 @@ - netstandard2.0 + net6.0 diff --git a/src/DataAccessLayers/BirdsiteLive.DAL/Contracts/ICachedTweetsDal.cs b/src/DataAccessLayers/BirdsiteLive.DAL/Contracts/ICachedTweetsDal.cs index 64ffe41..c9ddfa0 100644 --- a/src/DataAccessLayers/BirdsiteLive.DAL/Contracts/ICachedTweetsDal.cs +++ b/src/DataAccessLayers/BirdsiteLive.DAL/Contracts/ICachedTweetsDal.cs @@ -1,5 +1,7 @@ -using System.Threading.Tasks; +using System.Threading.Tasks; + using BirdsiteLive.DAL.Models; + using Tweetinvi.Models; namespace BirdsiteLive.DAL.Contracts @@ -10,4 +12,4 @@ namespace BirdsiteLive.DAL.Contracts Task GetTweetAsync(long tweetId); Task DeleteTweetAsync(long tweetId); } -} \ No newline at end of file +} diff --git a/src/DataAccessLayers/BirdsiteLive.DAL/Contracts/IDbInitializerDal.cs b/src/DataAccessLayers/BirdsiteLive.DAL/Contracts/IDbInitializerDal.cs index 9d7db56..517fe27 100644 --- a/src/DataAccessLayers/BirdsiteLive.DAL/Contracts/IDbInitializerDal.cs +++ b/src/DataAccessLayers/BirdsiteLive.DAL/Contracts/IDbInitializerDal.cs @@ -1,15 +1,15 @@ -using System; +using System; using System.Reflection; using System.Threading.Tasks; namespace BirdsiteLive.DAL.Contracts { public interface IDbInitializerDal - { + { Task GetCurrentDbVersionAsync(); Version GetMandatoryDbVersion(); Tuple[] GetMigrationPatterns(); Task MigrateDbAsync(Version from, Version to); Task InitDbAsync(); } -} \ No newline at end of file +} diff --git a/src/DataAccessLayers/BirdsiteLive.DAL/Contracts/IFollowersDal.cs b/src/DataAccessLayers/BirdsiteLive.DAL/Contracts/IFollowersDal.cs index fe87b28..987365e 100644 --- a/src/DataAccessLayers/BirdsiteLive.DAL/Contracts/IFollowersDal.cs +++ b/src/DataAccessLayers/BirdsiteLive.DAL/Contracts/IFollowersDal.cs @@ -1,5 +1,6 @@ -using System.Collections.Generic; +using System.Collections.Generic; using System.Threading.Tasks; + using BirdsiteLive.DAL.Models; namespace BirdsiteLive.DAL.Contracts @@ -7,8 +8,15 @@ namespace BirdsiteLive.DAL.Contracts public interface IFollowersDal { Task GetFollowerAsync(string acct, string host); - Task CreateFollowerAsync(string acct, string host, string inboxRoute, string sharedInboxRoute, string actorId, int[] followings = null, - Dictionary followingSyncStatus = null); + Task CreateFollowerAsync( + string acct, + string host, + string inboxRoute, + string sharedInboxRoute, + string actorId, + int[] followings = null, + Dictionary followingSyncStatus = null + ); Task GetFollowersAsync(int followedUserId); Task GetAllFollowersAsync(); Task UpdateFollowerAsync(Follower follower); @@ -17,4 +25,4 @@ namespace BirdsiteLive.DAL.Contracts Task GetFollowersCountAsync(); Task GetFailingFollowersCountAsync(); } -} \ No newline at end of file +} diff --git a/src/DataAccessLayers/BirdsiteLive.DAL/Contracts/ITwitterUserDal.cs b/src/DataAccessLayers/BirdsiteLive.DAL/Contracts/ITwitterUserDal.cs index ef2cc36..86927df 100644 --- a/src/DataAccessLayers/BirdsiteLive.DAL/Contracts/ITwitterUserDal.cs +++ b/src/DataAccessLayers/BirdsiteLive.DAL/Contracts/ITwitterUserDal.cs @@ -1,5 +1,6 @@ -using System; +using System; using System.Threading.Tasks; + using BirdsiteLive.DAL.Models; namespace BirdsiteLive.DAL.Contracts @@ -11,11 +12,17 @@ namespace BirdsiteLive.DAL.Contracts Task GetTwitterUserAsync(int id); Task GetAllTwitterUsersAsync(int maxNumber); Task GetAllTwitterUsersAsync(); - Task UpdateTwitterUserAsync(int id, long lastTweetPostedId, long lastTweetSynchronizedForAllFollowersId, int fetchingErrorCount, DateTime lastSync); + Task UpdateTwitterUserAsync( + int id, + long lastTweetPostedId, + long lastTweetSynchronizedForAllFollowersId, + int fetchingErrorCount, + DateTime lastSync + ); Task UpdateTwitterUserAsync(SyncTwitterUser user); Task DeleteTwitterUserAsync(string acct); Task DeleteTwitterUserAsync(int id); Task GetTwitterUsersCountAsync(); Task GetFailingTwitterUsersCountAsync(); } -} \ No newline at end of file +} diff --git a/src/DataAccessLayers/BirdsiteLive.DAL/DatabaseInitializer.cs b/src/DataAccessLayers/BirdsiteLive.DAL/DatabaseInitializer.cs index 39e1e84..0a48851 100644 --- a/src/DataAccessLayers/BirdsiteLive.DAL/DatabaseInitializer.cs +++ b/src/DataAccessLayers/BirdsiteLive.DAL/DatabaseInitializer.cs @@ -1,6 +1,7 @@ -using System; +using System; using System.Linq; using System.Threading.Tasks; + using BirdsiteLive.DAL.Contracts; namespace BirdsiteLive.DAL @@ -26,7 +27,8 @@ namespace BirdsiteLive.DAL var currentVersion = await _dbInitializerDal.GetCurrentDbVersionAsync(); var mandatoryVersion = _dbInitializerDal.GetMandatoryDbVersion(); - if (currentVersion == mandatoryVersion) return; + if (currentVersion == mandatoryVersion) + return; // Init Db if (currentVersion == null) @@ -37,10 +39,14 @@ namespace BirdsiteLive.DAL while (migrationPatterns.Any(x => x.Item1 == currentVersion)) { var migration = migrationPatterns.First(x => x.Item1 == currentVersion); - currentVersion = await _dbInitializerDal.MigrateDbAsync(migration.Item1, migration.Item2); + currentVersion = await _dbInitializerDal.MigrateDbAsync( + migration.Item1, + migration.Item2 + ); } - if (currentVersion != mandatoryVersion) throw new Exception("Migrating DB failed"); + if (currentVersion != mandatoryVersion) + throw new Exception("Migrating DB failed"); } } -} \ No newline at end of file +} diff --git a/src/DataAccessLayers/BirdsiteLive.DAL/Models/CachedTweet.cs b/src/DataAccessLayers/BirdsiteLive.DAL/Models/CachedTweet.cs index 25f5120..0c0a619 100644 --- a/src/DataAccessLayers/BirdsiteLive.DAL/Models/CachedTweet.cs +++ b/src/DataAccessLayers/BirdsiteLive.DAL/Models/CachedTweet.cs @@ -1,4 +1,4 @@ -using System; +using System; namespace BirdsiteLive.DAL.Models { @@ -27,5 +27,4 @@ namespace BirdsiteLive.DAL.Models public CachedTweet RetweetedTweet { get; } public string Url { get; } } - -} \ No newline at end of file +} diff --git a/src/DataAccessLayers/BirdsiteLive.DAL/Models/Follower.cs b/src/DataAccessLayers/BirdsiteLive.DAL/Models/Follower.cs index 357e32e..d0a2776 100644 --- a/src/DataAccessLayers/BirdsiteLive.DAL/Models/Follower.cs +++ b/src/DataAccessLayers/BirdsiteLive.DAL/Models/Follower.cs @@ -1,11 +1,11 @@ -using System.Collections.Generic; +using System.Collections.Generic; namespace BirdsiteLive.DAL.Models { public class Follower { public int Id { get; set; } - + public List Followings { get; set; } public Dictionary FollowingsSyncStatus { get; set; } @@ -17,4 +17,4 @@ namespace BirdsiteLive.DAL.Models public int PostingErrorCount { get; set; } } -} \ No newline at end of file +} diff --git a/src/DataAccessLayers/BirdsiteLive.DAL/Models/SyncTwitterUser.cs b/src/DataAccessLayers/BirdsiteLive.DAL/Models/SyncTwitterUser.cs index 8b18ba1..a55a859 100644 --- a/src/DataAccessLayers/BirdsiteLive.DAL/Models/SyncTwitterUser.cs +++ b/src/DataAccessLayers/BirdsiteLive.DAL/Models/SyncTwitterUser.cs @@ -1,4 +1,4 @@ -using System; +using System; namespace BirdsiteLive.DAL.Models { @@ -14,4 +14,4 @@ namespace BirdsiteLive.DAL.Models public int FetchingErrorCount { get; set; } //TODO: update DAL } -} \ No newline at end of file +} diff --git a/src/DataAccessLayers/BirdsiteLive.DAL/Tools/RandomGenerator.cs b/src/DataAccessLayers/BirdsiteLive.DAL/Tools/RandomGenerator.cs index fabbb5e..78a23c4 100644 --- a/src/DataAccessLayers/BirdsiteLive.DAL/Tools/RandomGenerator.cs +++ b/src/DataAccessLayers/BirdsiteLive.DAL/Tools/RandomGenerator.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Linq; namespace BirdsiteLive.DAL.Tools @@ -10,9 +10,9 @@ namespace BirdsiteLive.DAL.Tools public static string GetString(int length) { const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; - return new string(Enumerable.Repeat(chars, length) - .Select(s => s[Random.Next(s.Length)]).ToArray()); + return new string( + Enumerable.Repeat(chars, length).Select(s => s[Random.Next(s.Length)]).ToArray() + ); } - } -} \ No newline at end of file +} diff --git a/src/Tests/BSLManager.Tests/BSLManager.Tests.csproj b/src/Tests/BSLManager.Tests/BSLManager.Tests.csproj index 033cfe1..16b745c 100644 --- a/src/Tests/BSLManager.Tests/BSLManager.Tests.csproj +++ b/src/Tests/BSLManager.Tests/BSLManager.Tests.csproj @@ -1,7 +1,7 @@ - netcoreapp3.1 + net6.0 false diff --git a/src/Tests/BSLManager.Tests/Domain/FollowersListStateTests.cs b/src/Tests/BSLManager.Tests/Domain/FollowersListStateTests.cs index a0171a4..44c7a45 100644 --- a/src/Tests/BSLManager.Tests/Domain/FollowersListStateTests.cs +++ b/src/Tests/BSLManager.Tests/Domain/FollowersListStateTests.cs @@ -1,7 +1,10 @@ using System.Collections.Generic; using System.Linq; + using BirdsiteLive.DAL.Models; + using BSLManager.Domain; + using Microsoft.VisualStudio.TestTools.UnitTesting; namespace BSLManager.Tests @@ -21,7 +24,7 @@ namespace BSLManager.Tests Acct = "test", Host = "host1", Followings = new List() - }, + }, new Follower { Id = 1, @@ -50,7 +53,7 @@ namespace BSLManager.Tests state.Load(followers); state.FilterBy("test"); - + #region Validate Assert.AreEqual(2, state.GetDisplayableList().Count); #endregion @@ -292,7 +295,7 @@ namespace BSLManager.Tests var state = new FollowersListState(); state.Load(followers.ToList()); - + #region Validate state.FilterBy("data"); var list = state.GetDisplayableList(); diff --git a/src/Tests/BirdsiteLive.ActivityPub.Tests/ActivityTests.cs b/src/Tests/BirdsiteLive.ActivityPub.Tests/ActivityTests.cs index 1687ac4..eaa811c 100644 --- a/src/Tests/BirdsiteLive.ActivityPub.Tests/ActivityTests.cs +++ b/src/Tests/BirdsiteLive.ActivityPub.Tests/ActivityTests.cs @@ -1,4 +1,5 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; + using Newtonsoft.Json; namespace BirdsiteLive.ActivityPub.Tests diff --git a/src/Tests/BirdsiteLive.ActivityPub.Tests/ActorTests.cs b/src/Tests/BirdsiteLive.ActivityPub.Tests/ActorTests.cs index 628869c..bdcef3b 100644 --- a/src/Tests/BirdsiteLive.ActivityPub.Tests/ActorTests.cs +++ b/src/Tests/BirdsiteLive.ActivityPub.Tests/ActorTests.cs @@ -1,4 +1,5 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; +using Microsoft.VisualStudio.TestTools.UnitTesting; + using Newtonsoft.Json; namespace BirdsiteLive.ActivityPub.Tests @@ -12,24 +13,15 @@ namespace BirdsiteLive.ActivityPub.Tests var json = "{\"@context\":[\"https://www.w3.org/ns/activitystreams\",\"https://w3id.org/security/v1\",{\"manuallyApprovesFollowers\":\"as:manuallyApprovesFollowers\",\"toot\":\"http://joinmastodon.org/ns#\",\"featured\":{\"@id\":\"toot:featured\",\"@type\":\"@id\"},\"alsoKnownAs\":{\"@id\":\"as:alsoKnownAs\",\"@type\":\"@id\"},\"movedTo\":{\"@id\":\"as:movedTo\",\"@type\":\"@id\"},\"schema\":\"http://schema.org#\",\"PropertyValue\":\"schema:PropertyValue\",\"value\":\"schema:value\",\"IdentityProof\":\"toot:IdentityProof\",\"discoverable\":\"toot:discoverable\"}],\"id\":\"https://mastodon.technology/users/testtest\",\"type\":\"Person\",\"following\":\"https://mastodon.technology/users/testtest/following\",\"followers\":\"https://mastodon.technology/users/testtest/followers\",\"inbox\":\"https://mastodon.technology/users/testtest/inbox\",\"outbox\":\"https://mastodon.technology/users/testtest/outbox\",\"featured\":\"https://mastodon.technology/users/testtest/collections/featured\",\"preferredUsername\":\"testtest\",\"name\":\"TESTEST\",\"summary\":\"\u003cp\u003etest \u003cbr /\u003edsqdq65d4sq56d456q4d8zd4q685d45qd4sqd2q1d5zq56d465qsd4q65sd21qsd23q1s5d64qsd8q465d4s5q1d6qsd35qs4dq6sd84q\u003c/p\u003e\",\"url\":\"https://mastodon.technology/@testtest\",\"manuallyApprovesFollowers\":false,\"discoverable\":false,\"publicKey\":{\"id\":\"https://mastodon.technology/users/testtest#main-key\",\"owner\":\"https://mastodon.technology/users/testtest\",\"publicKeyPem\":\"-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAm7BlbWI/UD/YJj288h/5\nFB0gXZj0BjYVaK28uzTvb4w6eMu4qpbE9NI0bFqrloXzL3z6PaOCL4Myz9uJYolE\nZ9uNVi2OeZmHigNEOT3hkJWzddtrhkg8MLXKPdOETjhVWV3n+na7QWDDIXP7Fuvi\n+osA5LOoqtD1rYs87xUcWQPLCtVHs928FXsCdLO11ofXiNrancSzY17nkuufjWO+\ndLtvz1kx4Mt2V4Fu+DHskQAzPKU2tzGBrtlVQrk+1R63psIuZYDB6e4i7L6/d1Xl\nIQGmBeJfyxiuNIlbfZIbJ3xPYBQaVAnRKtyGVEFMWwZCqMySwc2LBX+rxI20zJ0R\n7wIDAQAB\n-----END PUBLIC KEY-----\n\"},\"tag\":[],\"attachment\":[],\"endpoints\":{\"sharedInbox\":\"https://mastodon.technology/inbox\"}}"; - var actor = JsonConvert.DeserializeObject(json); - - } [TestMethod] public void Serialize() { - var obj = new Actor - { - type = "Person", - id = "id" - }; + var obj = new Actor { type = "Person", id = "id" }; var json = JsonConvert.SerializeObject(obj); - - } } -} \ No newline at end of file +} diff --git a/src/Tests/BirdsiteLive.ActivityPub.Tests/ApDeserializerTests.cs b/src/Tests/BirdsiteLive.ActivityPub.Tests/ApDeserializerTests.cs index 3c85113..2f75786 100644 --- a/src/Tests/BirdsiteLive.ActivityPub.Tests/ApDeserializerTests.cs +++ b/src/Tests/BirdsiteLive.ActivityPub.Tests/ApDeserializerTests.cs @@ -1,4 +1,5 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; +using Microsoft.VisualStudio.TestTools.UnitTesting; + using Newtonsoft.Json; namespace BirdsiteLive.ActivityPub.Tests @@ -9,11 +10,15 @@ namespace BirdsiteLive.ActivityPub.Tests [TestMethod] public void FollowDeserializationTest() { - var json = "{ \"@context\":\"https://www.w3.org/ns/activitystreams\",\"id\":\"https://mastodon.technology/c94567cf-1fda-42ba-82fc-a0f82f63ccbe\",\"type\":\"Follow\",\"actor\":\"https://mastodon.technology/users/testtest\",\"object\":\"https://4a120ca2680e.ngrok.io/users/manu\"}"; + var json = + "{ \"@context\":\"https://www.w3.org/ns/activitystreams\",\"id\":\"https://mastodon.technology/c94567cf-1fda-42ba-82fc-a0f82f63ccbe\",\"type\":\"Follow\",\"actor\":\"https://mastodon.technology/users/testtest\",\"object\":\"https://4a120ca2680e.ngrok.io/users/manu\"}"; var data = ApDeserializer.ProcessActivity(json) as ActivityFollow; - Assert.AreEqual("https://mastodon.technology/c94567cf-1fda-42ba-82fc-a0f82f63ccbe", data.id); + Assert.AreEqual( + "https://mastodon.technology/c94567cf-1fda-42ba-82fc-a0f82f63ccbe", + data.id + ); Assert.AreEqual("Follow", data.type); Assert.AreEqual("https://4a120ca2680e.ngrok.io/users/manu", data.apObject); } @@ -25,7 +30,10 @@ namespace BirdsiteLive.ActivityPub.Tests "{\"@context\":\"https://www.w3.org/ns/activitystreams\",\"id\":\"https://mastodon.technology/users/testtest#follows/225982/undo\",\"type\":\"Undo\",\"actor\":\"https://mastodon.technology/users/testtest\",\"object\":{\"id\":\"https://mastodon.technology/c94567cf-1fda-42ba-82fc-a0f82f63ccbe\",\"type\":\"Follow\",\"actor\":\"https://mastodon.technology/users/testtest\",\"object\":\"https://4a120ca2680e.ngrok.io/users/manu\"}}"; var data = ApDeserializer.ProcessActivity(json) as ActivityUndoFollow; - Assert.AreEqual("https://mastodon.technology/users/testtest#follows/225982/undo", data.id); + Assert.AreEqual( + "https://mastodon.technology/users/testtest#follows/225982/undo", + data.id + ); Assert.AreEqual("Undo", data.type); Assert.AreEqual("Follow", data.apObject.type); Assert.AreEqual("https://mastodon.technology/users/testtest", data.apObject.actor); @@ -35,14 +43,17 @@ namespace BirdsiteLive.ActivityPub.Tests [TestMethod] public void AcceptDeserializationTest() { - var json = "{\"@context\":\"https://www.w3.org/ns/activitystreams\",\"id\":\"https://mamot.fr/users/testtest#accepts/follows/333879\",\"type\":\"Accept\",\"actor\":\"https://mamot.fr/users/testtest\",\"object\":{\"id\":\"https://85da1577f778.ngrok.io/f89dfd87-f5ce-4603-83d9-405c0e229989\",\"type\":\"Follow\",\"actor\":\"https://85da1577f778.ngrok.io/users/gra\",\"object\":\"https://mamot.fr/users/testtest\"}}"; - + var json = + "{\"@context\":\"https://www.w3.org/ns/activitystreams\",\"id\":\"https://mamot.fr/users/testtest#accepts/follows/333879\",\"type\":\"Accept\",\"actor\":\"https://mamot.fr/users/testtest\",\"object\":{\"id\":\"https://85da1577f778.ngrok.io/f89dfd87-f5ce-4603-83d9-405c0e229989\",\"type\":\"Follow\",\"actor\":\"https://85da1577f778.ngrok.io/users/gra\",\"object\":\"https://mamot.fr/users/testtest\"}}"; var data = ApDeserializer.ProcessActivity(json) as ActivityAcceptFollow; Assert.AreEqual("https://mamot.fr/users/testtest#accepts/follows/333879", data.id); Assert.AreEqual("Accept", data.type); Assert.AreEqual("https://mamot.fr/users/testtest", data.actor); - Assert.AreEqual("https://85da1577f778.ngrok.io/f89dfd87-f5ce-4603-83d9-405c0e229989", data.apObject.id); + Assert.AreEqual( + "https://85da1577f778.ngrok.io/f89dfd87-f5ce-4603-83d9-405c0e229989", + data.apObject.id + ); Assert.AreEqual("https://85da1577f778.ngrok.io/users/gra", data.apObject.actor); Assert.AreEqual("Follow", data.apObject.type); Assert.AreEqual("https://mamot.fr/users/testtest", data.apObject.apObject); @@ -57,4 +68,4 @@ namespace BirdsiteLive.ActivityPub.Tests // var data = ApDeserializer.ProcessActivity(json) as ActivityAcceptFollow; //} } -} \ No newline at end of file +} diff --git a/src/Tests/BirdsiteLive.ActivityPub.Tests/BirdsiteLive.ActivityPub.Tests.csproj b/src/Tests/BirdsiteLive.ActivityPub.Tests/BirdsiteLive.ActivityPub.Tests.csproj index 611d29e..85a8350 100644 --- a/src/Tests/BirdsiteLive.ActivityPub.Tests/BirdsiteLive.ActivityPub.Tests.csproj +++ b/src/Tests/BirdsiteLive.ActivityPub.Tests/BirdsiteLive.ActivityPub.Tests.csproj @@ -1,7 +1,7 @@ - netcoreapp3.1 + net6.0 false diff --git a/src/Tests/BirdsiteLive.Common.Tests/BirdsiteLive.Common.Tests.csproj b/src/Tests/BirdsiteLive.Common.Tests/BirdsiteLive.Common.Tests.csproj index 0a52603..cb48684 100644 --- a/src/Tests/BirdsiteLive.Common.Tests/BirdsiteLive.Common.Tests.csproj +++ b/src/Tests/BirdsiteLive.Common.Tests/BirdsiteLive.Common.Tests.csproj @@ -1,7 +1,7 @@ - netcoreapp3.1 + net6.0 false diff --git a/src/Tests/BirdsiteLive.Common.Tests/Regexes/HeaderRegexTests.cs b/src/Tests/BirdsiteLive.Common.Tests/Regexes/HeaderRegexTests.cs index 8c906ea..920e4be 100644 --- a/src/Tests/BirdsiteLive.Common.Tests/Regexes/HeaderRegexTests.cs +++ b/src/Tests/BirdsiteLive.Common.Tests/Regexes/HeaderRegexTests.cs @@ -1,4 +1,5 @@ using BirdsiteLive.Common.Regexes; + using Microsoft.VisualStudio.TestTools.UnitTesting; namespace BirdsiteLive.Common.Tests @@ -14,7 +15,10 @@ namespace BirdsiteLive.Common.Tests Assert.IsTrue(HeaderRegexes.HeaderSignature.IsMatch(input)); var result = HeaderRegexes.HeaderSignature.Match(input); Assert.AreEqual("keyId", result.Groups[1].ToString()); - Assert.AreEqual("https://misskey.tdl/users/8hwf6zy2k1#main-key", result.Groups[2].ToString()); + Assert.AreEqual( + "https://misskey.tdl/users/8hwf6zy2k1#main-key", + result.Groups[2].ToString() + ); } [TestMethod] @@ -42,12 +46,16 @@ namespace BirdsiteLive.Common.Tests [TestMethod] public void Signature_Test() { - var input = @"signature=""ISxp4HYhkGc83SsCC3zNZMVKBota7HqgWVg6KwaQVTQcUqt+UsWXPxB0XPhaYkqLnH3hJ+KVMdoEn3rbzcw8XZpjVt48o9OAKd0rsEZYkLoERnnFFhEw0GmVDEhdoU7gyoeOreWGsIca6Pf7TC0vGTtqez31zmvoeXvxHgqRhWQvlZM/ovFR2xN+vhmF7rZdkd6UaKOzy21K8B/Q84J7PWdbJ8i0rKieVPDIuTCy5B0iQpgs1TMaz6xKZR/KVzAr207m9Gkku2gnJ4YZHFuoa2ct5M5AtIPMPCsWTU8yaimTkPdNNezSOKV5a7T55HSvFeopLNcQKsWNMioKGpZP5hCIRKNk0Ekx0yDReE6xF/qliT7eSAGVJ/6sLQjBpBFMPKBNOrYTxueBJGtISjCZlxaIyTtJ1ErNuCrKHGjImpNvvJzTJOtu+vWnjTcUJL7N1Mw7PEreCZrNUyNuAldDWSMAFuD4HVA3+KZjpWCfjAbyelzVy2gs96CyE56o9FqJEaM5XVQhsMTpa8OSHdr2QZtKYw7Wng0d8vmbKEX1pdTVeEIhi4M9js39ZdzB4mb8JXSBE/GA6PoE5s+oH3+GoufzJYINCpk0Ulwo9g7HKm9NATnwEZZPq4NKto5mSYZKYRtqjZaa8lIALNhdvzv2+8+ifPLHlOigAUVqoupd9Aq="""; + var input = + @"signature=""ISxp4HYhkGc83SsCC3zNZMVKBota7HqgWVg6KwaQVTQcUqt+UsWXPxB0XPhaYkqLnH3hJ+KVMdoEn3rbzcw8XZpjVt48o9OAKd0rsEZYkLoERnnFFhEw0GmVDEhdoU7gyoeOreWGsIca6Pf7TC0vGTtqez31zmvoeXvxHgqRhWQvlZM/ovFR2xN+vhmF7rZdkd6UaKOzy21K8B/Q84J7PWdbJ8i0rKieVPDIuTCy5B0iQpgs1TMaz6xKZR/KVzAr207m9Gkku2gnJ4YZHFuoa2ct5M5AtIPMPCsWTU8yaimTkPdNNezSOKV5a7T55HSvFeopLNcQKsWNMioKGpZP5hCIRKNk0Ekx0yDReE6xF/qliT7eSAGVJ/6sLQjBpBFMPKBNOrYTxueBJGtISjCZlxaIyTtJ1ErNuCrKHGjImpNvvJzTJOtu+vWnjTcUJL7N1Mw7PEreCZrNUyNuAldDWSMAFuD4HVA3+KZjpWCfjAbyelzVy2gs96CyE56o9FqJEaM5XVQhsMTpa8OSHdr2QZtKYw7Wng0d8vmbKEX1pdTVeEIhi4M9js39ZdzB4mb8JXSBE/GA6PoE5s+oH3+GoufzJYINCpk0Ulwo9g7HKm9NATnwEZZPq4NKto5mSYZKYRtqjZaa8lIALNhdvzv2+8+ifPLHlOigAUVqoupd9Aq="""; Assert.IsTrue(HeaderRegexes.HeaderSignature.IsMatch(input)); var result = HeaderRegexes.HeaderSignature.Match(input); Assert.AreEqual("signature", result.Groups[1].ToString()); - Assert.AreEqual("ISxp4HYhkGc83SsCC3zNZMVKBota7HqgWVg6KwaQVTQcUqt+UsWXPxB0XPhaYkqLnH3hJ+KVMdoEn3rbzcw8XZpjVt48o9OAKd0rsEZYkLoERnnFFhEw0GmVDEhdoU7gyoeOreWGsIca6Pf7TC0vGTtqez31zmvoeXvxHgqRhWQvlZM/ovFR2xN+vhmF7rZdkd6UaKOzy21K8B/Q84J7PWdbJ8i0rKieVPDIuTCy5B0iQpgs1TMaz6xKZR/KVzAr207m9Gkku2gnJ4YZHFuoa2ct5M5AtIPMPCsWTU8yaimTkPdNNezSOKV5a7T55HSvFeopLNcQKsWNMioKGpZP5hCIRKNk0Ekx0yDReE6xF/qliT7eSAGVJ/6sLQjBpBFMPKBNOrYTxueBJGtISjCZlxaIyTtJ1ErNuCrKHGjImpNvvJzTJOtu+vWnjTcUJL7N1Mw7PEreCZrNUyNuAldDWSMAFuD4HVA3+KZjpWCfjAbyelzVy2gs96CyE56o9FqJEaM5XVQhsMTpa8OSHdr2QZtKYw7Wng0d8vmbKEX1pdTVeEIhi4M9js39ZdzB4mb8JXSBE/GA6PoE5s+oH3+GoufzJYINCpk0Ulwo9g7HKm9NATnwEZZPq4NKto5mSYZKYRtqjZaa8lIALNhdvzv2+8+ifPLHlOigAUVqoupd9Aq=", result.Groups[2].ToString()); + Assert.AreEqual( + "ISxp4HYhkGc83SsCC3zNZMVKBota7HqgWVg6KwaQVTQcUqt+UsWXPxB0XPhaYkqLnH3hJ+KVMdoEn3rbzcw8XZpjVt48o9OAKd0rsEZYkLoERnnFFhEw0GmVDEhdoU7gyoeOreWGsIca6Pf7TC0vGTtqez31zmvoeXvxHgqRhWQvlZM/ovFR2xN+vhmF7rZdkd6UaKOzy21K8B/Q84J7PWdbJ8i0rKieVPDIuTCy5B0iQpgs1TMaz6xKZR/KVzAr207m9Gkku2gnJ4YZHFuoa2ct5M5AtIPMPCsWTU8yaimTkPdNNezSOKV5a7T55HSvFeopLNcQKsWNMioKGpZP5hCIRKNk0Ekx0yDReE6xF/qliT7eSAGVJ/6sLQjBpBFMPKBNOrYTxueBJGtISjCZlxaIyTtJ1ErNuCrKHGjImpNvvJzTJOtu+vWnjTcUJL7N1Mw7PEreCZrNUyNuAldDWSMAFuD4HVA3+KZjpWCfjAbyelzVy2gs96CyE56o9FqJEaM5XVQhsMTpa8OSHdr2QZtKYw7Wng0d8vmbKEX1pdTVeEIhi4M9js39ZdzB4mb8JXSBE/GA6PoE5s+oH3+GoufzJYINCpk0Ulwo9g7HKm9NATnwEZZPq4NKto5mSYZKYRtqjZaa8lIALNhdvzv2+8+ifPLHlOigAUVqoupd9Aq=", + result.Groups[2].ToString() + ); } } } diff --git a/src/Tests/BirdsiteLive.Cryptography.Tests/BirdsiteLive.Cryptography.Tests.csproj b/src/Tests/BirdsiteLive.Cryptography.Tests/BirdsiteLive.Cryptography.Tests.csproj index 0c9c0a6..95af7c8 100644 --- a/src/Tests/BirdsiteLive.Cryptography.Tests/BirdsiteLive.Cryptography.Tests.csproj +++ b/src/Tests/BirdsiteLive.Cryptography.Tests/BirdsiteLive.Cryptography.Tests.csproj @@ -1,7 +1,7 @@ - netcoreapp3.1 + net6.0 false diff --git a/src/Tests/BirdsiteLive.Cryptography.Tests/MagicKeyTests.cs b/src/Tests/BirdsiteLive.Cryptography.Tests/MagicKeyTests.cs index 413aa53..13368d4 100644 --- a/src/Tests/BirdsiteLive.Cryptography.Tests/MagicKeyTests.cs +++ b/src/Tests/BirdsiteLive.Cryptography.Tests/MagicKeyTests.cs @@ -1,5 +1,7 @@ -using System.Threading.Tasks; +using System.Threading.Tasks; + using Microsoft.VisualStudio.TestTools.UnitTesting; + using NuGet.Frameworks; namespace BirdsiteLive.Cryptography.Tests @@ -16,4 +18,4 @@ namespace BirdsiteLive.Cryptography.Tests Assert.IsNotNull(magicKey); } } -} \ No newline at end of file +} diff --git a/src/Tests/BirdsiteLive.Cryptography.Tests/RsaKeysTests.cs b/src/Tests/BirdsiteLive.Cryptography.Tests/RsaKeysTests.cs index 2e4ae5e..2ed0be5 100644 --- a/src/Tests/BirdsiteLive.Cryptography.Tests/RsaKeysTests.cs +++ b/src/Tests/BirdsiteLive.Cryptography.Tests/RsaKeysTests.cs @@ -1,4 +1,4 @@ -//using System.Security.Cryptography; +//using System.Security.Cryptography; //using Microsoft.VisualStudio.TestTools.UnitTesting; //using MyProject.Data.Encryption; @@ -31,4 +31,4 @@ // } // } -//} \ No newline at end of file +//} diff --git a/src/Tests/BirdsiteLive.DAL.Postgres.Tests/BirdsiteLive.DAL.Postgres.Tests.csproj b/src/Tests/BirdsiteLive.DAL.Postgres.Tests/BirdsiteLive.DAL.Postgres.Tests.csproj index da05ef2..694e43f 100644 --- a/src/Tests/BirdsiteLive.DAL.Postgres.Tests/BirdsiteLive.DAL.Postgres.Tests.csproj +++ b/src/Tests/BirdsiteLive.DAL.Postgres.Tests/BirdsiteLive.DAL.Postgres.Tests.csproj @@ -1,7 +1,7 @@ - netcoreapp3.1 + net6.0 false diff --git a/src/Tests/BirdsiteLive.DAL.Postgres.Tests/DataAccessLayers/Base/PostgresTestingBase.cs b/src/Tests/BirdsiteLive.DAL.Postgres.Tests/DataAccessLayers/Base/PostgresTestingBase.cs index 72bf352..45a0567 100644 --- a/src/Tests/BirdsiteLive.DAL.Postgres.Tests/DataAccessLayers/Base/PostgresTestingBase.cs +++ b/src/Tests/BirdsiteLive.DAL.Postgres.Tests/DataAccessLayers/Base/PostgresTestingBase.cs @@ -1,4 +1,4 @@ -using BirdsiteLive.DAL.Postgres.Settings; +using BirdsiteLive.DAL.Postgres.Settings; using BirdsiteLive.DAL.Postgres.Tools; using BirdsiteLive.DAL.Tools; @@ -8,13 +8,14 @@ namespace BirdsiteLive.DAL.Postgres.Tests.DataAccessLayers.Base { protected readonly PostgresSettings _settings; protected readonly PostgresTools _tools; - + #region Ctor public PostgresTestingBase() { _settings = new PostgresSettings { - ConnString = "Host=127.0.0.1;Username=postgres;Password=mysecretpassword;Database=mytestdb", + ConnString = + "Host=127.0.0.1;Username=birdtest;Password=mysecretpassword;Database=birdsitetest", DbVersionTableName = "DbVersionTableName" + RandomGenerator.GetString(4), CachedTweetsTableName = "CachedTweetsTableName" + RandomGenerator.GetString(4), FollowersTableName = "FollowersTableName" + RandomGenerator.GetString(4), @@ -24,4 +25,4 @@ namespace BirdsiteLive.DAL.Postgres.Tests.DataAccessLayers.Base } #endregion } -} \ No newline at end of file +} diff --git a/src/Tests/BirdsiteLive.DAL.Postgres.Tests/DataAccessLayers/CachedTweetsPostgresDalTests.cs b/src/Tests/BirdsiteLive.DAL.Postgres.Tests/DataAccessLayers/CachedTweetsPostgresDalTests.cs index 24672c3..57498de 100644 --- a/src/Tests/BirdsiteLive.DAL.Postgres.Tests/DataAccessLayers/CachedTweetsPostgresDalTests.cs +++ b/src/Tests/BirdsiteLive.DAL.Postgres.Tests/DataAccessLayers/CachedTweetsPostgresDalTests.cs @@ -1,8 +1,10 @@ -using System; +using System; using System.Threading.Tasks; + using BirdsiteLive.DAL.Models; using BirdsiteLive.DAL.Postgres.DataAccessLayers; using BirdsiteLive.DAL.Postgres.Tests.DataAccessLayers.Base; + using Microsoft.VisualStudio.TestTools.UnitTesting; namespace BirdsiteLive.DAL.Postgres.Tests.DataAccessLayers @@ -78,4 +80,4 @@ namespace BirdsiteLive.DAL.Postgres.Tests.DataAccessLayers Assert.IsNull(result); } } -} \ No newline at end of file +} diff --git a/src/Tests/BirdsiteLive.DAL.Postgres.Tests/DataAccessLayers/DbInitializerPostgresDalTests.cs b/src/Tests/BirdsiteLive.DAL.Postgres.Tests/DataAccessLayers/DbInitializerPostgresDalTests.cs index a186dc3..d490665 100644 --- a/src/Tests/BirdsiteLive.DAL.Postgres.Tests/DataAccessLayers/DbInitializerPostgresDalTests.cs +++ b/src/Tests/BirdsiteLive.DAL.Postgres.Tests/DataAccessLayers/DbInitializerPostgresDalTests.cs @@ -1,7 +1,9 @@ -using System; +using System; using System.Threading.Tasks; + using BirdsiteLive.DAL.Postgres.DataAccessLayers; using BirdsiteLive.DAL.Postgres.Tests.DataAccessLayers.Base; + using Microsoft.VisualStudio.TestTools.UnitTesting; namespace BirdsiteLive.DAL.Postgres.Tests.DataAccessLayers @@ -17,7 +19,7 @@ namespace BirdsiteLive.DAL.Postgres.Tests.DataAccessLayers { await dal.DeleteAllAsync(); } - catch (Exception ) { } + catch (Exception) { } } [TestMethod] @@ -42,4 +44,4 @@ namespace BirdsiteLive.DAL.Postgres.Tests.DataAccessLayers Assert.AreEqual(mandatory.Major, current.Major); } } -} \ No newline at end of file +} diff --git a/src/Tests/BirdsiteLive.DAL.Postgres.Tests/DataAccessLayers/FollowersPostgresDalTests.cs b/src/Tests/BirdsiteLive.DAL.Postgres.Tests/DataAccessLayers/FollowersPostgresDalTests.cs index a22df0f..da96c5a 100644 --- a/src/Tests/BirdsiteLive.DAL.Postgres.Tests/DataAccessLayers/FollowersPostgresDalTests.cs +++ b/src/Tests/BirdsiteLive.DAL.Postgres.Tests/DataAccessLayers/FollowersPostgresDalTests.cs @@ -1,10 +1,12 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; + using BirdsiteLive.DAL.Models; using BirdsiteLive.DAL.Postgres.DataAccessLayers; using BirdsiteLive.DAL.Postgres.Tests.DataAccessLayers.Base; + using Microsoft.VisualStudio.TestTools.UnitTesting; namespace BirdsiteLive.DAL.Postgres.Tests.DataAccessLayers @@ -35,16 +37,24 @@ namespace BirdsiteLive.DAL.Postgres.Tests.DataAccessLayers var following = new[] { 12, 19, 23 }; var followingSync = new Dictionary() { - {12, 165L}, - {19, 166L}, - {23, 167L} + { 12, 165L }, + { 19, 166L }, + { 23, 167L } }; var inboxRoute = "/myhandle/inbox"; var sharedInboxRoute = "/inbox"; var actorId = $"https://{host}/{acct}"; var dal = new FollowersPostgresDal(_settings); - await dal.CreateFollowerAsync(acct, host, inboxRoute, sharedInboxRoute, actorId, following, followingSync); + await dal.CreateFollowerAsync( + acct, + host, + inboxRoute, + sharedInboxRoute, + actorId, + following, + followingSync + ); var result = await dal.GetFollowerAsync(acct, host); @@ -72,7 +82,15 @@ namespace BirdsiteLive.DAL.Postgres.Tests.DataAccessLayers var actorId = $"https://{host}/{acct}"; var dal = new FollowersPostgresDal(_settings); - await dal.CreateFollowerAsync(acct, host, inboxRoute, sharedInboxRoute, actorId, null, null); + await dal.CreateFollowerAsync( + acct, + host, + inboxRoute, + sharedInboxRoute, + actorId, + null, + null + ); var result = await dal.GetFollowerAsync(acct, host); @@ -103,16 +121,24 @@ namespace BirdsiteLive.DAL.Postgres.Tests.DataAccessLayers var following = new[] { 12, 19, 23 }; var followingSync = new Dictionary() { - {12, 165L}, - {19, 166L}, - {23, 167L} + { 12, 165L }, + { 19, 166L }, + { 23, 167L } }; var inboxRoute = "/myhandle/inbox"; string sharedInboxRoute = null; var actorId = $"https://{host}/{acct}"; var dal = new FollowersPostgresDal(_settings); - await dal.CreateFollowerAsync(acct, host, inboxRoute, sharedInboxRoute, actorId, following, followingSync); + await dal.CreateFollowerAsync( + acct, + host, + inboxRoute, + sharedInboxRoute, + actorId, + following, + followingSync + ); var result = await dal.GetFollowerAsync(acct, host); @@ -135,7 +161,7 @@ namespace BirdsiteLive.DAL.Postgres.Tests.DataAccessLayers { var dal = new FollowersPostgresDal(_settings); - //User 1 + //User 1 var acct = "myhandle1"; var host = "domain.ext"; var following = new[] { 1, 2, 3 }; @@ -143,25 +169,49 @@ namespace BirdsiteLive.DAL.Postgres.Tests.DataAccessLayers var inboxRoute = "/myhandle1/inbox"; var sharedInboxRoute = "/inbox"; var actorId = $"https://{host}/{acct}"; - await dal.CreateFollowerAsync(acct, host, inboxRoute, sharedInboxRoute, actorId, following, followingSync); + await dal.CreateFollowerAsync( + acct, + host, + inboxRoute, + sharedInboxRoute, + actorId, + following, + followingSync + ); - //User 2 + //User 2 acct = "myhandle2"; host = "domain.ext"; following = new[] { 2, 4, 5 }; inboxRoute = "/myhandle2/inbox"; sharedInboxRoute = "/inbox2"; actorId = $"https://{host}/{acct}"; - await dal.CreateFollowerAsync(acct, host, inboxRoute, sharedInboxRoute, actorId, following, followingSync); + await dal.CreateFollowerAsync( + acct, + host, + inboxRoute, + sharedInboxRoute, + actorId, + following, + followingSync + ); - //User 2 + //User 2 acct = "myhandle3"; host = "domain.ext"; following = new[] { 1 }; inboxRoute = "/myhandle3/inbox"; sharedInboxRoute = "/inbox3"; actorId = $"https://{host}/{acct}"; - await dal.CreateFollowerAsync(acct, host, inboxRoute, sharedInboxRoute, actorId, following, followingSync); + await dal.CreateFollowerAsync( + acct, + host, + inboxRoute, + sharedInboxRoute, + actorId, + following, + followingSync + ); var result = await dal.GetFollowersAsync(2); Assert.AreEqual(2, result.Length); @@ -178,7 +228,7 @@ namespace BirdsiteLive.DAL.Postgres.Tests.DataAccessLayers { var dal = new FollowersPostgresDal(_settings); - //User 1 + //User 1 var acct = "myhandle1"; var host = "domain.ext"; var following = new[] { 1, 2, 3 }; @@ -186,25 +236,49 @@ namespace BirdsiteLive.DAL.Postgres.Tests.DataAccessLayers var inboxRoute = "/myhandle1/inbox"; var sharedInboxRoute = "/inbox"; var actorId = $"https://{host}/{acct}"; - await dal.CreateFollowerAsync(acct, host, inboxRoute, sharedInboxRoute, actorId, following, followingSync); + await dal.CreateFollowerAsync( + acct, + host, + inboxRoute, + sharedInboxRoute, + actorId, + following, + followingSync + ); - //User 2 + //User 2 acct = "myhandle2"; host = "domain.ext"; following = new[] { 2, 4, 5 }; inboxRoute = "/myhandle2/inbox"; sharedInboxRoute = "/inbox2"; actorId = $"https://{host}/{acct}"; - await dal.CreateFollowerAsync(acct, host, inboxRoute, sharedInboxRoute, actorId, following, followingSync); + await dal.CreateFollowerAsync( + acct, + host, + inboxRoute, + sharedInboxRoute, + actorId, + following, + followingSync + ); - //User 2 + //User 2 acct = "myhandle3"; host = "domain.ext"; following = new[] { 1 }; inboxRoute = "/myhandle3/inbox"; sharedInboxRoute = "/inbox3"; actorId = $"https://{host}/{acct}"; - await dal.CreateFollowerAsync(acct, host, inboxRoute, sharedInboxRoute, actorId, following, followingSync); + await dal.CreateFollowerAsync( + acct, + host, + inboxRoute, + sharedInboxRoute, + actorId, + following, + followingSync + ); var result = await dal.GetAllFollowersAsync(); Assert.AreEqual(3, result.Length); @@ -218,7 +292,7 @@ namespace BirdsiteLive.DAL.Postgres.Tests.DataAccessLayers var result = await dal.GetFollowersCountAsync(); Assert.AreEqual(0, result); - //User 1 + //User 1 var acct = "myhandle1"; var host = "domain.ext"; var following = new[] { 1, 2, 3 }; @@ -226,16 +300,32 @@ namespace BirdsiteLive.DAL.Postgres.Tests.DataAccessLayers var inboxRoute = "/myhandle1/inbox"; var sharedInboxRoute = "/inbox"; var actorId = $"https://{host}/{acct}"; - await dal.CreateFollowerAsync(acct, host, inboxRoute, sharedInboxRoute, actorId, following, followingSync); + await dal.CreateFollowerAsync( + acct, + host, + inboxRoute, + sharedInboxRoute, + actorId, + following, + followingSync + ); - //User 2 + //User 2 acct = "myhandle2"; host = "domain.ext"; following = new[] { 2, 4, 5 }; inboxRoute = "/myhandle2/inbox"; sharedInboxRoute = "/inbox2"; actorId = $"https://{host}/{acct}"; - await dal.CreateFollowerAsync(acct, host, inboxRoute, sharedInboxRoute, actorId, following, followingSync); + await dal.CreateFollowerAsync( + acct, + host, + inboxRoute, + sharedInboxRoute, + actorId, + following, + followingSync + ); //User 3 acct = "myhandle3"; @@ -244,7 +334,15 @@ namespace BirdsiteLive.DAL.Postgres.Tests.DataAccessLayers inboxRoute = "/myhandle3/inbox"; sharedInboxRoute = "/inbox3"; actorId = $"https://{host}/{acct}"; - await dal.CreateFollowerAsync(acct, host, inboxRoute, sharedInboxRoute, actorId, following, followingSync); + await dal.CreateFollowerAsync( + acct, + host, + inboxRoute, + sharedInboxRoute, + actorId, + following, + followingSync + ); result = await dal.GetFollowersCountAsync(); Assert.AreEqual(3, result); @@ -258,7 +356,7 @@ namespace BirdsiteLive.DAL.Postgres.Tests.DataAccessLayers var result = await dal.GetFailingFollowersCountAsync(); Assert.AreEqual(0, result); - //User 1 + //User 1 var acct = "myhandle1"; var host = "domain.ext"; var following = new[] { 1, 2, 3 }; @@ -266,16 +364,32 @@ namespace BirdsiteLive.DAL.Postgres.Tests.DataAccessLayers var inboxRoute = "/myhandle1/inbox"; var sharedInboxRoute = "/inbox"; var actorId = $"https://{host}/{acct}"; - await dal.CreateFollowerAsync(acct, host, inboxRoute, sharedInboxRoute, actorId, following, followingSync); + await dal.CreateFollowerAsync( + acct, + host, + inboxRoute, + sharedInboxRoute, + actorId, + following, + followingSync + ); - //User 2 + //User 2 acct = "myhandle2"; host = "domain.ext"; following = new[] { 2, 4, 5 }; inboxRoute = "/myhandle2/inbox"; sharedInboxRoute = "/inbox2"; actorId = $"https://{host}/{acct}"; - await dal.CreateFollowerAsync(acct, host, inboxRoute, sharedInboxRoute, actorId, following, followingSync); + await dal.CreateFollowerAsync( + acct, + host, + inboxRoute, + sharedInboxRoute, + actorId, + following, + followingSync + ); var follower = await dal.GetFollowerAsync(acct, host); follower.PostingErrorCount = 1; @@ -288,7 +402,15 @@ namespace BirdsiteLive.DAL.Postgres.Tests.DataAccessLayers inboxRoute = "/myhandle3/inbox"; sharedInboxRoute = "/inbox3"; actorId = $"https://{host}/{acct}"; - await dal.CreateFollowerAsync(acct, host, inboxRoute, sharedInboxRoute, actorId, following, followingSync); + await dal.CreateFollowerAsync( + acct, + host, + inboxRoute, + sharedInboxRoute, + actorId, + following, + followingSync + ); follower = await dal.GetFollowerAsync(acct, host); follower.PostingErrorCount = 50; @@ -306,37 +428,52 @@ namespace BirdsiteLive.DAL.Postgres.Tests.DataAccessLayers var following = new[] { 12, 19, 23 }; var followingSync = new Dictionary() { - {12, 165L}, - {19, 166L}, - {23, 167L} + { 12, 165L }, + { 19, 166L }, + { 23, 167L } }; var inboxRoute = "/myhandle/inbox"; var sharedInboxRoute = "/inbox"; var actorId = $"https://{host}/{acct}"; var dal = new FollowersPostgresDal(_settings); - await dal.CreateFollowerAsync(acct, host, inboxRoute, sharedInboxRoute, actorId, following, followingSync); + await dal.CreateFollowerAsync( + acct, + host, + inboxRoute, + sharedInboxRoute, + actorId, + following, + followingSync + ); var result = await dal.GetFollowerAsync(acct, host); var updatedFollowing = new List { 12, 19, 23, 24 }; - var updatedFollowingSync = new Dictionary(){ - {12, 170L}, - {19, 171L}, - {23, 172L}, - {24, 173L} + var updatedFollowingSync = new Dictionary() + { + { 12, 170L }, + { 19, 171L }, + { 23, 172L }, + { 24, 173L } }; result.Followings = updatedFollowing.ToList(); result.FollowingsSyncStatus = updatedFollowingSync; result.PostingErrorCount = 10; - + await dal.UpdateFollowerAsync(result); result = await dal.GetFollowerAsync(acct, host); Assert.AreEqual(updatedFollowing.Count, result.Followings.Count); Assert.AreEqual(updatedFollowing[0], result.Followings[0]); Assert.AreEqual(updatedFollowingSync.Count, result.FollowingsSyncStatus.Count); - Assert.AreEqual(updatedFollowingSync.First().Key, result.FollowingsSyncStatus.First().Key); - Assert.AreEqual(updatedFollowingSync.First().Value, result.FollowingsSyncStatus.First().Value); + Assert.AreEqual( + updatedFollowingSync.First().Key, + result.FollowingsSyncStatus.First().Key + ); + Assert.AreEqual( + updatedFollowingSync.First().Value, + result.FollowingsSyncStatus.First().Value + ); Assert.AreEqual(10, result.PostingErrorCount); } @@ -348,24 +485,28 @@ namespace BirdsiteLive.DAL.Postgres.Tests.DataAccessLayers var following = new[] { 12, 19, 23 }; var followingSync = new Dictionary() { - {12, 165L}, - {19, 166L}, - {23, 167L} + { 12, 165L }, + { 19, 166L }, + { 23, 167L } }; var inboxRoute = "/myhandle/inbox"; var sharedInboxRoute = "/inbox"; var actorId = $"https://{host}/{acct}"; var dal = new FollowersPostgresDal(_settings); - await dal.CreateFollowerAsync(acct, host, inboxRoute, sharedInboxRoute, actorId, following, followingSync); + await dal.CreateFollowerAsync( + acct, + host, + inboxRoute, + sharedInboxRoute, + actorId, + following, + followingSync + ); var result = await dal.GetFollowerAsync(acct, host); var updatedFollowing = new[] { 12, 19 }; - var updatedFollowingSync = new Dictionary() - { - {12, 170L}, - {19, 171L} - }; + var updatedFollowingSync = new Dictionary() { { 12, 170L }, { 19, 171L } }; result.Followings = updatedFollowing.ToList(); result.FollowingsSyncStatus = updatedFollowingSync; result.PostingErrorCount = 5; @@ -376,8 +517,14 @@ namespace BirdsiteLive.DAL.Postgres.Tests.DataAccessLayers Assert.AreEqual(updatedFollowing.Length, result.Followings.Count); Assert.AreEqual(updatedFollowing[0], result.Followings[0]); Assert.AreEqual(updatedFollowingSync.Count, result.FollowingsSyncStatus.Count); - Assert.AreEqual(updatedFollowingSync.First().Key, result.FollowingsSyncStatus.First().Key); - Assert.AreEqual(updatedFollowingSync.First().Value, result.FollowingsSyncStatus.First().Value); + Assert.AreEqual( + updatedFollowingSync.First().Key, + result.FollowingsSyncStatus.First().Key + ); + Assert.AreEqual( + updatedFollowingSync.First().Value, + result.FollowingsSyncStatus.First().Value + ); Assert.AreEqual(5, result.PostingErrorCount); } @@ -389,16 +536,24 @@ namespace BirdsiteLive.DAL.Postgres.Tests.DataAccessLayers var following = new[] { 12, 19, 23 }; var followingSync = new Dictionary() { - {12, 165L}, - {19, 166L}, - {23, 167L} + { 12, 165L }, + { 19, 166L }, + { 23, 167L } }; var inboxRoute = "/myhandle/inbox"; var sharedInboxRoute = "/inbox"; var actorId = $"https://{host}/{acct}"; var dal = new FollowersPostgresDal(_settings); - await dal.CreateFollowerAsync(acct, host, inboxRoute, sharedInboxRoute, actorId, following, followingSync); + await dal.CreateFollowerAsync( + acct, + host, + inboxRoute, + sharedInboxRoute, + actorId, + following, + followingSync + ); var result = await dal.GetFollowerAsync(acct, host); Assert.AreEqual(0, result.PostingErrorCount); @@ -427,10 +582,7 @@ namespace BirdsiteLive.DAL.Postgres.Tests.DataAccessLayers [ExpectedException(typeof(ArgumentException))] public async Task Update_NoFollowerId() { - var follower = new Follower - { - Id = default - }; + var follower = new Follower { Id = default }; var dal = new FollowersPostgresDal(_settings); await dal.UpdateFollowerAsync(follower); @@ -444,16 +596,24 @@ namespace BirdsiteLive.DAL.Postgres.Tests.DataAccessLayers var following = new[] { 12, 19, 23 }; var followingSync = new Dictionary() { - {12, 165L}, - {19, 166L}, - {23, 167L} + { 12, 165L }, + { 19, 166L }, + { 23, 167L } }; var inboxRoute = "/myhandle/inbox"; var sharedInboxRoute = "/inbox"; var actorId = $"https://{host}/{acct}"; var dal = new FollowersPostgresDal(_settings); - await dal.CreateFollowerAsync(acct, host, inboxRoute, sharedInboxRoute, actorId, following, followingSync); + await dal.CreateFollowerAsync( + acct, + host, + inboxRoute, + sharedInboxRoute, + actorId, + following, + followingSync + ); var result = await dal.GetFollowerAsync(acct, host); Assert.IsNotNull(result); @@ -471,16 +631,24 @@ namespace BirdsiteLive.DAL.Postgres.Tests.DataAccessLayers var following = new[] { 12, 19, 23 }; var followingSync = new Dictionary() { - {12, 165L}, - {19, 166L}, - {23, 167L} + { 12, 165L }, + { 19, 166L }, + { 23, 167L } }; var inboxRoute = "/myhandle/inbox"; var sharedInboxRoute = "/inbox"; var actorId = $"https://{host}/{acct}"; var dal = new FollowersPostgresDal(_settings); - await dal.CreateFollowerAsync(acct, host, inboxRoute, sharedInboxRoute, actorId, following, followingSync); + await dal.CreateFollowerAsync( + acct, + host, + inboxRoute, + sharedInboxRoute, + actorId, + following, + followingSync + ); var result = await dal.GetFollowerAsync(acct, host); Assert.IsNotNull(result); @@ -514,4 +682,4 @@ namespace BirdsiteLive.DAL.Postgres.Tests.DataAccessLayers await dal.DeleteFollowerAsync("acct", string.Empty); } } -} \ No newline at end of file +} diff --git a/src/Tests/BirdsiteLive.DAL.Postgres.Tests/DataAccessLayers/TwitterUserPostgresDalTests.cs b/src/Tests/BirdsiteLive.DAL.Postgres.Tests/DataAccessLayers/TwitterUserPostgresDalTests.cs index 0b007b6..dd9e883 100644 --- a/src/Tests/BirdsiteLive.DAL.Postgres.Tests/DataAccessLayers/TwitterUserPostgresDalTests.cs +++ b/src/Tests/BirdsiteLive.DAL.Postgres.Tests/DataAccessLayers/TwitterUserPostgresDalTests.cs @@ -1,10 +1,12 @@ -using System; +using System; using System.Diagnostics; using System.Linq; using System.Threading.Tasks; using System.Xml; + using BirdsiteLive.DAL.Postgres.DataAccessLayers; using BirdsiteLive.DAL.Postgres.Tests.DataAccessLayers.Base; + using Microsoft.VisualStudio.TestTools.UnitTesting; namespace BirdsiteLive.DAL.Postgres.Tests.DataAccessLayers @@ -82,12 +84,17 @@ namespace BirdsiteLive.DAL.Postgres.Tests.DataAccessLayers await dal.CreateTwitterUserAsync(acct, lastTweetId); var result = await dal.GetTwitterUserAsync(acct); - var updatedLastTweetId = 1600L; var updatedLastSyncId = 1550L; var now = DateTime.Now; var errors = 15; - await dal.UpdateTwitterUserAsync(result.Id, updatedLastTweetId, updatedLastSyncId, errors, now); + await dal.UpdateTwitterUserAsync( + result.Id, + updatedLastTweetId, + updatedLastSyncId, + errors, + now + ); result = await dal.GetTwitterUserAsync(acct); @@ -109,7 +116,6 @@ namespace BirdsiteLive.DAL.Postgres.Tests.DataAccessLayers await dal.CreateTwitterUserAsync(acct, lastTweetId); var result = await dal.GetTwitterUserAsync(acct); - var updatedLastTweetId = 1600L; var updatedLastSyncId = 1550L; var now = DateTime.Now; @@ -240,7 +246,7 @@ namespace BirdsiteLive.DAL.Postgres.Tests.DataAccessLayers for (var i = 0; i < 1000; i++) { var acct = $"myid{i}"; - var lastTweetId = i+10; + var lastTweetId = i + 10; await dal.CreateTwitterUserAsync(acct, lastTweetId); } @@ -286,7 +292,13 @@ namespace BirdsiteLive.DAL.Postgres.Tests.DataAccessLayers { var user = allUsers[i]; var date = i % 2 == 0 ? oldest : newest; - await dal.UpdateTwitterUserAsync(user.Id, user.LastTweetPostedId, user.LastTweetSynchronizedForAllFollowersId, 0, date); + await dal.UpdateTwitterUserAsync( + user.Id, + user.LastTweetPostedId, + user.LastTweetSynchronizedForAllFollowersId, + 0, + date + ); } var result = await dal.GetAllTwitterUsersAsync(10); @@ -297,7 +309,9 @@ namespace BirdsiteLive.DAL.Postgres.Tests.DataAccessLayers Assert.IsFalse(result[0].LastTweetSynchronizedForAllFollowersId == default); foreach (var acc in result) - Assert.IsTrue(Math.Abs((acc.LastSync - oldest.ToUniversalTime()).TotalMilliseconds) < 1000); + Assert.IsTrue( + Math.Abs((acc.LastSync - oldest.ToUniversalTime()).TotalMilliseconds) < 1000 + ); } [TestMethod] @@ -350,7 +364,7 @@ namespace BirdsiteLive.DAL.Postgres.Tests.DataAccessLayers if (i == 0 || i == 2 || i == 3) { var t = await dal.GetTwitterUserAsync(acct); - await dal.UpdateTwitterUserAsync(t.Id ,1L,2L, 50+i*2, DateTime.Now); + await dal.UpdateTwitterUserAsync(t.Id, 1L, 2L, 50 + i * 2, DateTime.Now); } } @@ -358,4 +372,4 @@ namespace BirdsiteLive.DAL.Postgres.Tests.DataAccessLayers Assert.AreEqual(3, result); } } -} \ No newline at end of file +} diff --git a/src/Tests/BirdsiteLive.DAL.Tests/BirdsiteLive.DAL.Tests.csproj b/src/Tests/BirdsiteLive.DAL.Tests/BirdsiteLive.DAL.Tests.csproj index 0992b02..026af77 100644 --- a/src/Tests/BirdsiteLive.DAL.Tests/BirdsiteLive.DAL.Tests.csproj +++ b/src/Tests/BirdsiteLive.DAL.Tests/BirdsiteLive.DAL.Tests.csproj @@ -1,7 +1,7 @@ - netcoreapp3.1 + net6.0 false diff --git a/src/Tests/BirdsiteLive.DAL.Tests/DatabaseInitializerTests.cs b/src/Tests/BirdsiteLive.DAL.Tests/DatabaseInitializerTests.cs index ba11321..fd614ea 100644 --- a/src/Tests/BirdsiteLive.DAL.Tests/DatabaseInitializerTests.cs +++ b/src/Tests/BirdsiteLive.DAL.Tests/DatabaseInitializerTests.cs @@ -1,8 +1,11 @@ using System; using System.Linq; using System.Threading.Tasks; + using BirdsiteLive.DAL.Contracts; + using Microsoft.VisualStudio.TestTools.UnitTesting; + using Moq; namespace BirdsiteLive.DAL.Tests @@ -21,13 +24,9 @@ namespace BirdsiteLive.DAL.Tests #region Mocks var dbInitializerDal = new Mock(MockBehavior.Strict); - dbInitializerDal - .Setup(x => x.GetCurrentDbVersionAsync()) - .ReturnsAsync(current); + dbInitializerDal.Setup(x => x.GetCurrentDbVersionAsync()).ReturnsAsync(current); - dbInitializerDal - .Setup(x => x.GetMandatoryDbVersion()) - .Returns(mandatory); + dbInitializerDal.Setup(x => x.GetMandatoryDbVersion()).Returns(mandatory); #endregion var dbInitializer = new DatabaseInitializer(dbInitializerDal.Object); @@ -51,21 +50,13 @@ namespace BirdsiteLive.DAL.Tests #region Mocks var dbInitializerDal = new Mock(MockBehavior.Strict); - dbInitializerDal - .Setup(x => x.GetCurrentDbVersionAsync()) - .ReturnsAsync(current); + dbInitializerDal.Setup(x => x.GetCurrentDbVersionAsync()).ReturnsAsync(current); - dbInitializerDal - .Setup(x => x.GetMandatoryDbVersion()) - .Returns(mandatory); + dbInitializerDal.Setup(x => x.GetMandatoryDbVersion()).Returns(mandatory); - dbInitializerDal - .Setup(x => x.InitDbAsync()) - .ReturnsAsync(new Version(1, 0)); + dbInitializerDal.Setup(x => x.InitDbAsync()).ReturnsAsync(new Version(1, 0)); - dbInitializerDal - .Setup(x => x.GetMigrationPatterns()) - .Returns(migrationPatterns); + dbInitializerDal.Setup(x => x.GetMigrationPatterns()).Returns(migrationPatterns); #endregion var dbInitializer = new DatabaseInitializer(dbInitializerDal.Object); @@ -85,38 +76,33 @@ namespace BirdsiteLive.DAL.Tests var migrationPatterns = new Tuple[] { - new Tuple(new Version(1,0), new Version(1,7)), - new Tuple(new Version(1,7), new Version(2,0)), - new Tuple(new Version(2,0), new Version(2,3)) + new Tuple(new Version(1, 0), new Version(1, 7)), + new Tuple(new Version(1, 7), new Version(2, 0)), + new Tuple(new Version(2, 0), new Version(2, 3)) }; #endregion #region Mocks var dbInitializerDal = new Mock(MockBehavior.Strict); - dbInitializerDal - .Setup(x => x.GetCurrentDbVersionAsync()) - .ReturnsAsync(current); + dbInitializerDal.Setup(x => x.GetCurrentDbVersionAsync()).ReturnsAsync(current); - dbInitializerDal - .Setup(x => x.GetMandatoryDbVersion()) - .Returns(mandatory); + dbInitializerDal.Setup(x => x.GetMandatoryDbVersion()).Returns(mandatory); - dbInitializerDal - .Setup(x => x.InitDbAsync()) - .ReturnsAsync(new Version(1, 0)); + dbInitializerDal.Setup(x => x.InitDbAsync()).ReturnsAsync(new Version(1, 0)); - dbInitializerDal - .Setup(x => x.GetMigrationPatterns()) - .Returns(migrationPatterns); + dbInitializerDal.Setup(x => x.GetMigrationPatterns()).Returns(migrationPatterns); foreach (var m in migrationPatterns) { dbInitializerDal - .Setup(x => x.MigrateDbAsync( - It.Is(y => y == m.Item1), - It.Is(y => y == m.Item2) - )) + .Setup( + x => + x.MigrateDbAsync( + It.Is(y => y == m.Item1), + It.Is(y => y == m.Item2) + ) + ) .ReturnsAsync(m.Item2); } #endregion @@ -138,34 +124,31 @@ namespace BirdsiteLive.DAL.Tests var migrationPatterns = new Tuple[] { - new Tuple(new Version(1,0), new Version(1,7)), - new Tuple(new Version(1,7), new Version(2,0)), - new Tuple(new Version(2,0), new Version(2,3)) + new Tuple(new Version(1, 0), new Version(1, 7)), + new Tuple(new Version(1, 7), new Version(2, 0)), + new Tuple(new Version(2, 0), new Version(2, 3)) }; #endregion #region Mocks var dbInitializerDal = new Mock(MockBehavior.Strict); - dbInitializerDal - .Setup(x => x.GetCurrentDbVersionAsync()) - .ReturnsAsync(current); + dbInitializerDal.Setup(x => x.GetCurrentDbVersionAsync()).ReturnsAsync(current); - dbInitializerDal - .Setup(x => x.GetMandatoryDbVersion()) - .Returns(mandatory); + dbInitializerDal.Setup(x => x.GetMandatoryDbVersion()).Returns(mandatory); - dbInitializerDal - .Setup(x => x.GetMigrationPatterns()) - .Returns(migrationPatterns); + dbInitializerDal.Setup(x => x.GetMigrationPatterns()).Returns(migrationPatterns); foreach (var m in migrationPatterns.Skip(1)) { dbInitializerDal - .Setup(x => x.MigrateDbAsync( - It.Is(y => y == m.Item1), - It.Is(y => y == m.Item2) - )) + .Setup( + x => + x.MigrateDbAsync( + It.Is(y => y == m.Item1), + It.Is(y => y == m.Item2) + ) + ) .ReturnsAsync(m.Item2); } #endregion @@ -188,38 +171,33 @@ namespace BirdsiteLive.DAL.Tests var migrationPatterns = new Tuple[] { - new Tuple(new Version(1,0), new Version(1,7)), - new Tuple(new Version(1,7), new Version(2,0)), - new Tuple(new Version(2,0), new Version(2,2)) + new Tuple(new Version(1, 0), new Version(1, 7)), + new Tuple(new Version(1, 7), new Version(2, 0)), + new Tuple(new Version(2, 0), new Version(2, 2)) }; #endregion #region Mocks var dbInitializerDal = new Mock(MockBehavior.Strict); - dbInitializerDal - .Setup(x => x.GetCurrentDbVersionAsync()) - .ReturnsAsync(current); + dbInitializerDal.Setup(x => x.GetCurrentDbVersionAsync()).ReturnsAsync(current); - dbInitializerDal - .Setup(x => x.GetMandatoryDbVersion()) - .Returns(mandatory); + dbInitializerDal.Setup(x => x.GetMandatoryDbVersion()).Returns(mandatory); - dbInitializerDal - .Setup(x => x.InitDbAsync()) - .ReturnsAsync(new Version(1, 0)); + dbInitializerDal.Setup(x => x.InitDbAsync()).ReturnsAsync(new Version(1, 0)); - dbInitializerDal - .Setup(x => x.GetMigrationPatterns()) - .Returns(migrationPatterns); + dbInitializerDal.Setup(x => x.GetMigrationPatterns()).Returns(migrationPatterns); foreach (var m in migrationPatterns) { dbInitializerDal - .Setup(x => x.MigrateDbAsync( - It.Is(y => y == m.Item1), - It.Is(y => y == m.Item2) - )) + .Setup( + x => + x.MigrateDbAsync( + It.Is(y => y == m.Item1), + It.Is(y => y == m.Item2) + ) + ) .ReturnsAsync(m.Item2); } #endregion diff --git a/src/Tests/BirdsiteLive.Domain.Tests/BirdsiteLive.Domain.Tests.csproj b/src/Tests/BirdsiteLive.Domain.Tests/BirdsiteLive.Domain.Tests.csproj index 626c941..33f9f0c 100644 --- a/src/Tests/BirdsiteLive.Domain.Tests/BirdsiteLive.Domain.Tests.csproj +++ b/src/Tests/BirdsiteLive.Domain.Tests/BirdsiteLive.Domain.Tests.csproj @@ -1,7 +1,7 @@ - netcoreapp3.1 + net6.0 false diff --git a/src/Tests/BirdsiteLive.Domain.Tests/BusinessUseCases/ProcessFollowUserTests.cs b/src/Tests/BirdsiteLive.Domain.Tests/BusinessUseCases/ProcessFollowUserTests.cs index 0fb03ae..0eacbbc 100644 --- a/src/Tests/BirdsiteLive.Domain.Tests/BusinessUseCases/ProcessFollowUserTests.cs +++ b/src/Tests/BirdsiteLive.Domain.Tests/BusinessUseCases/ProcessFollowUserTests.cs @@ -1,10 +1,14 @@ -using System.Collections.Generic; +using System.Collections.Generic; using System.Threading.Tasks; + using BirdsiteLive.DAL.Contracts; using BirdsiteLive.DAL.Models; using BirdsiteLive.Domain.BusinessUseCases; + using Microsoft.VisualStudio.TestTools.UnitTesting; + using Moq; + using Org.BouncyCastle.Crypto.Prng; namespace BirdsiteLive.Domain.Tests.BusinessUseCases @@ -51,21 +55,31 @@ namespace BirdsiteLive.Domain.Tests.BusinessUseCases .ReturnsAsync(follower); followersDalMock - .Setup(x => x.CreateFollowerAsync( - It.Is(y => y == username), - It.Is(y => y == domain), - It.Is(y => y == followerInbox), - It.Is(y => y == inbox), - It.Is(y => y == actorId), - null, - null)) + .Setup( + x => + x.CreateFollowerAsync( + It.Is(y => y == username), + It.Is(y => y == domain), + It.Is(y => y == followerInbox), + It.Is(y => y == inbox), + It.Is(y => y == actorId), + null, + null + ) + ) .Returns(Task.CompletedTask); followersDalMock - .Setup(x => x.UpdateFollowerAsync( - It.Is(y => y.Followings.Contains(twitterUser.Id) - && y.FollowingsSyncStatus[twitterUser.Id] == -1) - )) + .Setup( + x => + x.UpdateFollowerAsync( + It.Is( + y => + y.Followings.Contains(twitterUser.Id) + && y.FollowingsSyncStatus[twitterUser.Id] == -1 + ) + ) + ) .Returns(Task.CompletedTask); var twitterUserDalMock = new Mock(MockBehavior.Strict); @@ -75,9 +89,13 @@ namespace BirdsiteLive.Domain.Tests.BusinessUseCases .ReturnsAsync(twitterUser); twitterUserDalMock - .Setup(x => x.CreateTwitterUserAsync( - It.Is(y => y == twitterName), - It.Is(y => y == -1))) + .Setup( + x => + x.CreateTwitterUserAsync( + It.Is(y => y == twitterName), + It.Is(y => y == -1) + ) + ) .Returns(Task.CompletedTask); #endregion @@ -100,7 +118,7 @@ namespace BirdsiteLive.Domain.Tests.BusinessUseCases var followerInbox = "/user/testest"; var inbox = "/inbox"; var actorId = "actorUrl"; - + var follower = new Follower { Id = 1, @@ -126,12 +144,18 @@ namespace BirdsiteLive.Domain.Tests.BusinessUseCases followersDalMock .Setup(x => x.GetFollowerAsync(username, domain)) .ReturnsAsync(follower); - + followersDalMock - .Setup(x => x.UpdateFollowerAsync( - It.Is(y => y.Followings.Contains(twitterUser.Id) - && y.FollowingsSyncStatus[twitterUser.Id] == -1) - )) + .Setup( + x => + x.UpdateFollowerAsync( + It.Is( + y => + y.Followings.Contains(twitterUser.Id) + && y.FollowingsSyncStatus[twitterUser.Id] == -1 + ) + ) + ) .Returns(Task.CompletedTask); var twitterUserDalMock = new Mock(MockBehavior.Strict); @@ -149,4 +173,4 @@ namespace BirdsiteLive.Domain.Tests.BusinessUseCases #endregion } } -} \ No newline at end of file +} diff --git a/src/Tests/BirdsiteLive.Domain.Tests/BusinessUseCases/ProcessUnfollowUserTests.cs b/src/Tests/BirdsiteLive.Domain.Tests/BusinessUseCases/ProcessUnfollowUserTests.cs index 9bd83e3..b6d4a69 100644 --- a/src/Tests/BirdsiteLive.Domain.Tests/BusinessUseCases/ProcessUnfollowUserTests.cs +++ b/src/Tests/BirdsiteLive.Domain.Tests/BusinessUseCases/ProcessUnfollowUserTests.cs @@ -1,9 +1,12 @@ -using System.Collections.Generic; +using System.Collections.Generic; using System.Threading.Tasks; + using BirdsiteLive.DAL.Contracts; using BirdsiteLive.DAL.Models; using BirdsiteLive.Domain.BusinessUseCases; + using Microsoft.VisualStudio.TestTools.UnitTesting; + using Moq; namespace BirdsiteLive.Domain.Tests.BusinessUseCases @@ -24,13 +27,16 @@ namespace BirdsiteLive.Domain.Tests.BusinessUseCases var followersDalMock = new Mock(MockBehavior.Strict); followersDalMock .Setup(x => x.GetFollowerAsync(username, domain)) - .ReturnsAsync((Follower) null); + .ReturnsAsync((Follower)null); var twitterUserDalMock = new Mock(MockBehavior.Strict); #endregion - var action = new ProcessUndoFollowUser(followersDalMock.Object, twitterUserDalMock.Object); - await action.ExecuteAsync(username, domain, twitterName ); + var action = new ProcessUndoFollowUser( + followersDalMock.Object, + twitterUserDalMock.Object + ); + await action.ExecuteAsync(username, domain, twitterName); #region Validations followersDalMock.VerifyAll(); @@ -68,7 +74,10 @@ namespace BirdsiteLive.Domain.Tests.BusinessUseCases .ReturnsAsync((SyncTwitterUser)null); #endregion - var action = new ProcessUndoFollowUser(followersDalMock.Object, twitterUserDalMock.Object); + var action = new ProcessUndoFollowUser( + followersDalMock.Object, + twitterUserDalMock.Object + ); await action.ExecuteAsync(username, domain, twitterName); #region Validations @@ -91,7 +100,7 @@ namespace BirdsiteLive.Domain.Tests.BusinessUseCases Acct = username, Host = domain, Followings = new List { 2, 3 }, - FollowingsSyncStatus = new Dictionary { { 2, 460 }, { 3, 563} } + FollowingsSyncStatus = new Dictionary { { 2, 460 }, { 3, 563 } } }; var twitterUser = new SyncTwitterUser @@ -102,11 +111,7 @@ namespace BirdsiteLive.Domain.Tests.BusinessUseCases LastTweetSynchronizedForAllFollowersId = 460 }; - var followerList = new List - { - new Follower(), - new Follower() - }; + var followerList = new List { new Follower(), new Follower() }; #endregion #region Mocks @@ -116,10 +121,16 @@ namespace BirdsiteLive.Domain.Tests.BusinessUseCases .ReturnsAsync(follower); followersDalMock - .Setup(x => x.UpdateFollowerAsync( - It.Is(y => !y.Followings.Contains(twitterUser.Id) - && !y.FollowingsSyncStatus.ContainsKey(twitterUser.Id)) - )) + .Setup( + x => + x.UpdateFollowerAsync( + It.Is( + y => + !y.Followings.Contains(twitterUser.Id) + && !y.FollowingsSyncStatus.ContainsKey(twitterUser.Id) + ) + ) + ) .Returns(Task.CompletedTask); followersDalMock @@ -132,7 +143,10 @@ namespace BirdsiteLive.Domain.Tests.BusinessUseCases .ReturnsAsync(twitterUser); #endregion - var action = new ProcessUndoFollowUser(followersDalMock.Object, twitterUserDalMock.Object); + var action = new ProcessUndoFollowUser( + followersDalMock.Object, + twitterUserDalMock.Object + ); await action.ExecuteAsync(username, domain, twitterName); #region Validations @@ -176,10 +190,13 @@ namespace BirdsiteLive.Domain.Tests.BusinessUseCases .ReturnsAsync(follower); followersDalMock - .Setup(x => x.DeleteFollowerAsync( - It.Is(y => y == username), - It.Is(y => y == domain) - )) + .Setup( + x => + x.DeleteFollowerAsync( + It.Is(y => y == username), + It.Is(y => y == domain) + ) + ) .Returns(Task.CompletedTask); followersDalMock @@ -192,13 +209,14 @@ namespace BirdsiteLive.Domain.Tests.BusinessUseCases .ReturnsAsync(twitterUser); twitterUserDalMock - .Setup(x => x.DeleteTwitterUserAsync( - It.Is(y => y == twitterName) - )) + .Setup(x => x.DeleteTwitterUserAsync(It.Is(y => y == twitterName))) .Returns(Task.CompletedTask); #endregion - var action = new ProcessUndoFollowUser(followersDalMock.Object, twitterUserDalMock.Object); + var action = new ProcessUndoFollowUser( + followersDalMock.Object, + twitterUserDalMock.Object + ); await action.ExecuteAsync(username, domain, twitterName); #region Validations @@ -207,4 +225,4 @@ namespace BirdsiteLive.Domain.Tests.BusinessUseCases #endregion } } -} \ No newline at end of file +} diff --git a/src/Tests/BirdsiteLive.Domain.Tests/Repository/ModerationRepositoryTests.cs b/src/Tests/BirdsiteLive.Domain.Tests/Repository/ModerationRepositoryTests.cs index 30ffb8e..03c8753 100644 --- a/src/Tests/BirdsiteLive.Domain.Tests/Repository/ModerationRepositoryTests.cs +++ b/src/Tests/BirdsiteLive.Domain.Tests/Repository/ModerationRepositoryTests.cs @@ -1,5 +1,6 @@ -using BirdsiteLive.Common.Settings; +using BirdsiteLive.Common.Settings; using BirdsiteLive.Domain.Repository; + using Microsoft.VisualStudio.TestTools.UnitTesting; namespace BirdsiteLive.Domain.Tests.Repository @@ -12,17 +13,20 @@ namespace BirdsiteLive.Domain.Tests.Repository public void GetModerationType_Follower_WhiteListing_Test() { #region Stubs - var settings = new ModerationSettings - { - FollowersWhiteListing = "@me@domain.ext" - }; + var settings = new ModerationSettings { FollowersWhiteListing = "@me@domain.ext" }; #endregion var repo = new ModerationRepository(settings); #region Validations - Assert.AreEqual(ModerationTypeEnum.WhiteListing ,repo.GetModerationType(ModerationEntityTypeEnum.Follower)); - Assert.AreEqual(ModerationTypeEnum.None, repo.GetModerationType(ModerationEntityTypeEnum.TwitterAccount)); + Assert.AreEqual( + ModerationTypeEnum.WhiteListing, + repo.GetModerationType(ModerationEntityTypeEnum.Follower) + ); + Assert.AreEqual( + ModerationTypeEnum.None, + repo.GetModerationType(ModerationEntityTypeEnum.TwitterAccount) + ); #endregion } @@ -39,8 +43,14 @@ namespace BirdsiteLive.Domain.Tests.Repository var repo = new ModerationRepository(settings); #region Validations - Assert.AreEqual(ModerationTypeEnum.None, repo.GetModerationType(ModerationEntityTypeEnum.Follower)); - Assert.AreEqual(ModerationTypeEnum.WhiteListing, repo.GetModerationType(ModerationEntityTypeEnum.TwitterAccount)); + Assert.AreEqual( + ModerationTypeEnum.None, + repo.GetModerationType(ModerationEntityTypeEnum.Follower) + ); + Assert.AreEqual( + ModerationTypeEnum.WhiteListing, + repo.GetModerationType(ModerationEntityTypeEnum.TwitterAccount) + ); #endregion } @@ -58,8 +68,14 @@ namespace BirdsiteLive.Domain.Tests.Repository var repo = new ModerationRepository(settings); #region Validations - Assert.AreEqual(ModerationTypeEnum.WhiteListing, repo.GetModerationType(ModerationEntityTypeEnum.Follower)); - Assert.AreEqual(ModerationTypeEnum.WhiteListing, repo.GetModerationType(ModerationEntityTypeEnum.TwitterAccount)); + Assert.AreEqual( + ModerationTypeEnum.WhiteListing, + repo.GetModerationType(ModerationEntityTypeEnum.Follower) + ); + Assert.AreEqual( + ModerationTypeEnum.WhiteListing, + repo.GetModerationType(ModerationEntityTypeEnum.TwitterAccount) + ); #endregion } @@ -67,17 +83,20 @@ namespace BirdsiteLive.Domain.Tests.Repository public void GetModerationType_Follower_BlackListing_Test() { #region Stubs - var settings = new ModerationSettings - { - FollowersBlackListing = "@me@domain.ext" - }; + var settings = new ModerationSettings { FollowersBlackListing = "@me@domain.ext" }; #endregion var repo = new ModerationRepository(settings); #region Validations - Assert.AreEqual(ModerationTypeEnum.BlackListing, repo.GetModerationType(ModerationEntityTypeEnum.Follower)); - Assert.AreEqual(ModerationTypeEnum.None, repo.GetModerationType(ModerationEntityTypeEnum.TwitterAccount)); + Assert.AreEqual( + ModerationTypeEnum.BlackListing, + repo.GetModerationType(ModerationEntityTypeEnum.Follower) + ); + Assert.AreEqual( + ModerationTypeEnum.None, + repo.GetModerationType(ModerationEntityTypeEnum.TwitterAccount) + ); #endregion } @@ -94,8 +113,14 @@ namespace BirdsiteLive.Domain.Tests.Repository var repo = new ModerationRepository(settings); #region Validations - Assert.AreEqual(ModerationTypeEnum.None, repo.GetModerationType(ModerationEntityTypeEnum.Follower)); - Assert.AreEqual(ModerationTypeEnum.BlackListing, repo.GetModerationType(ModerationEntityTypeEnum.TwitterAccount)); + Assert.AreEqual( + ModerationTypeEnum.None, + repo.GetModerationType(ModerationEntityTypeEnum.Follower) + ); + Assert.AreEqual( + ModerationTypeEnum.BlackListing, + repo.GetModerationType(ModerationEntityTypeEnum.TwitterAccount) + ); #endregion } @@ -113,8 +138,14 @@ namespace BirdsiteLive.Domain.Tests.Repository var repo = new ModerationRepository(settings); #region Validations - Assert.AreEqual(ModerationTypeEnum.BlackListing, repo.GetModerationType(ModerationEntityTypeEnum.Follower)); - Assert.AreEqual(ModerationTypeEnum.BlackListing, repo.GetModerationType(ModerationEntityTypeEnum.TwitterAccount)); + Assert.AreEqual( + ModerationTypeEnum.BlackListing, + repo.GetModerationType(ModerationEntityTypeEnum.Follower) + ); + Assert.AreEqual( + ModerationTypeEnum.BlackListing, + repo.GetModerationType(ModerationEntityTypeEnum.TwitterAccount) + ); #endregion } @@ -132,8 +163,14 @@ namespace BirdsiteLive.Domain.Tests.Repository var repo = new ModerationRepository(settings); #region Validations - Assert.AreEqual(ModerationTypeEnum.WhiteListing, repo.GetModerationType(ModerationEntityTypeEnum.Follower)); - Assert.AreEqual(ModerationTypeEnum.None, repo.GetModerationType(ModerationEntityTypeEnum.TwitterAccount)); + Assert.AreEqual( + ModerationTypeEnum.WhiteListing, + repo.GetModerationType(ModerationEntityTypeEnum.Follower) + ); + Assert.AreEqual( + ModerationTypeEnum.None, + repo.GetModerationType(ModerationEntityTypeEnum.TwitterAccount) + ); #endregion } @@ -151,8 +188,14 @@ namespace BirdsiteLive.Domain.Tests.Repository var repo = new ModerationRepository(settings); #region Validations - Assert.AreEqual(ModerationTypeEnum.None, repo.GetModerationType(ModerationEntityTypeEnum.Follower)); - Assert.AreEqual(ModerationTypeEnum.WhiteListing, repo.GetModerationType(ModerationEntityTypeEnum.TwitterAccount)); + Assert.AreEqual( + ModerationTypeEnum.None, + repo.GetModerationType(ModerationEntityTypeEnum.Follower) + ); + Assert.AreEqual( + ModerationTypeEnum.WhiteListing, + repo.GetModerationType(ModerationEntityTypeEnum.TwitterAccount) + ); #endregion } @@ -172,8 +215,14 @@ namespace BirdsiteLive.Domain.Tests.Repository var repo = new ModerationRepository(settings); #region Validations - Assert.AreEqual(ModerationTypeEnum.WhiteListing, repo.GetModerationType(ModerationEntityTypeEnum.Follower)); - Assert.AreEqual(ModerationTypeEnum.WhiteListing, repo.GetModerationType(ModerationEntityTypeEnum.TwitterAccount)); + Assert.AreEqual( + ModerationTypeEnum.WhiteListing, + repo.GetModerationType(ModerationEntityTypeEnum.Follower) + ); + Assert.AreEqual( + ModerationTypeEnum.WhiteListing, + repo.GetModerationType(ModerationEntityTypeEnum.TwitterAccount) + ); #endregion } #endregion @@ -183,17 +232,20 @@ namespace BirdsiteLive.Domain.Tests.Repository public void CheckStatus_Follower_WhiteListing_Test() { #region Stubs - var settings = new ModerationSettings - { - FollowersWhiteListing = "@me@domain.ext" - }; + var settings = new ModerationSettings { FollowersWhiteListing = "@me@domain.ext" }; #endregion var repo = new ModerationRepository(settings); #region Validations - Assert.AreEqual(ModeratedTypeEnum.WhiteListed, repo.CheckStatus(ModerationEntityTypeEnum.Follower, "@me@domain.ext")); - Assert.AreEqual(ModeratedTypeEnum.None, repo.CheckStatus(ModerationEntityTypeEnum.Follower, "@me2@domain.ext")); + Assert.AreEqual( + ModeratedTypeEnum.WhiteListed, + repo.CheckStatus(ModerationEntityTypeEnum.Follower, "@me@domain.ext") + ); + Assert.AreEqual( + ModeratedTypeEnum.None, + repo.CheckStatus(ModerationEntityTypeEnum.Follower, "@me2@domain.ext") + ); #endregion } @@ -201,18 +253,24 @@ namespace BirdsiteLive.Domain.Tests.Repository public void CheckStatus_Follower_WhiteListing_Instance_Test() { #region Stubs - var settings = new ModerationSettings - { - FollowersWhiteListing = "domain.ext" - }; + var settings = new ModerationSettings { FollowersWhiteListing = "domain.ext" }; #endregion var repo = new ModerationRepository(settings); #region Validations - Assert.AreEqual(ModeratedTypeEnum.WhiteListed, repo.CheckStatus(ModerationEntityTypeEnum.Follower, "@me@domain.ext")); - Assert.AreEqual(ModeratedTypeEnum.WhiteListed, repo.CheckStatus(ModerationEntityTypeEnum.Follower, "@me2@domain.ext")); - Assert.AreEqual(ModeratedTypeEnum.None, repo.CheckStatus(ModerationEntityTypeEnum.Follower, "@me2@domain2.ext")); + Assert.AreEqual( + ModeratedTypeEnum.WhiteListed, + repo.CheckStatus(ModerationEntityTypeEnum.Follower, "@me@domain.ext") + ); + Assert.AreEqual( + ModeratedTypeEnum.WhiteListed, + repo.CheckStatus(ModerationEntityTypeEnum.Follower, "@me2@domain.ext") + ); + Assert.AreEqual( + ModeratedTypeEnum.None, + repo.CheckStatus(ModerationEntityTypeEnum.Follower, "@me2@domain2.ext") + ); #endregion } @@ -220,19 +278,28 @@ namespace BirdsiteLive.Domain.Tests.Repository public void CheckStatus_Follower_WhiteListing_SubDomain_Test() { #region Stubs - var settings = new ModerationSettings - { - FollowersWhiteListing = "*.domain.ext" - }; + var settings = new ModerationSettings { FollowersWhiteListing = "*.domain.ext" }; #endregion var repo = new ModerationRepository(settings); #region Validations - Assert.AreEqual(ModeratedTypeEnum.WhiteListed, repo.CheckStatus(ModerationEntityTypeEnum.Follower, "@me@s.domain.ext")); - Assert.AreEqual(ModeratedTypeEnum.WhiteListed, repo.CheckStatus(ModerationEntityTypeEnum.Follower, "@me2@s2.domain.ext")); - Assert.AreEqual(ModeratedTypeEnum.None, repo.CheckStatus(ModerationEntityTypeEnum.Follower, "@me2@domain.ext")); - Assert.AreEqual(ModeratedTypeEnum.None, repo.CheckStatus(ModerationEntityTypeEnum.Follower, "@me2@domain2.ext")); + Assert.AreEqual( + ModeratedTypeEnum.WhiteListed, + repo.CheckStatus(ModerationEntityTypeEnum.Follower, "@me@s.domain.ext") + ); + Assert.AreEqual( + ModeratedTypeEnum.WhiteListed, + repo.CheckStatus(ModerationEntityTypeEnum.Follower, "@me2@s2.domain.ext") + ); + Assert.AreEqual( + ModeratedTypeEnum.None, + repo.CheckStatus(ModerationEntityTypeEnum.Follower, "@me2@domain.ext") + ); + Assert.AreEqual( + ModeratedTypeEnum.None, + repo.CheckStatus(ModerationEntityTypeEnum.Follower, "@me2@domain2.ext") + ); #endregion } @@ -240,17 +307,20 @@ namespace BirdsiteLive.Domain.Tests.Repository public void CheckStatus_TwitterAccount_WhiteListing_Test() { #region Stubs - var settings = new ModerationSettings - { - TwitterAccountsWhiteListing = "handle" - }; + var settings = new ModerationSettings { TwitterAccountsWhiteListing = "handle" }; #endregion var repo = new ModerationRepository(settings); #region Validations - Assert.AreEqual(ModeratedTypeEnum.WhiteListed, repo.CheckStatus(ModerationEntityTypeEnum.TwitterAccount, "handle")); - Assert.AreEqual(ModeratedTypeEnum.None, repo.CheckStatus(ModerationEntityTypeEnum.TwitterAccount, "handle2")); + Assert.AreEqual( + ModeratedTypeEnum.WhiteListed, + repo.CheckStatus(ModerationEntityTypeEnum.TwitterAccount, "handle") + ); + Assert.AreEqual( + ModeratedTypeEnum.None, + repo.CheckStatus(ModerationEntityTypeEnum.TwitterAccount, "handle2") + ); #endregion } @@ -258,17 +328,20 @@ namespace BirdsiteLive.Domain.Tests.Repository public void CheckStatus_Follower_BlackListing_Test() { #region Stubs - var settings = new ModerationSettings - { - FollowersBlackListing = "@me@domain.ext" - }; + var settings = new ModerationSettings { FollowersBlackListing = "@me@domain.ext" }; #endregion var repo = new ModerationRepository(settings); #region Validations - Assert.AreEqual(ModeratedTypeEnum.BlackListed, repo.CheckStatus(ModerationEntityTypeEnum.Follower, "@me@domain.ext")); - Assert.AreEqual(ModeratedTypeEnum.None, repo.CheckStatus(ModerationEntityTypeEnum.Follower, "@me2@domain.ext")); + Assert.AreEqual( + ModeratedTypeEnum.BlackListed, + repo.CheckStatus(ModerationEntityTypeEnum.Follower, "@me@domain.ext") + ); + Assert.AreEqual( + ModeratedTypeEnum.None, + repo.CheckStatus(ModerationEntityTypeEnum.Follower, "@me2@domain.ext") + ); #endregion } @@ -276,17 +349,20 @@ namespace BirdsiteLive.Domain.Tests.Repository public void CheckStatus_TwitterAccount_BlackListing_Test() { #region Stubs - var settings = new ModerationSettings - { - TwitterAccountsBlackListing = "handle" - }; + var settings = new ModerationSettings { TwitterAccountsBlackListing = "handle" }; #endregion var repo = new ModerationRepository(settings); #region Validations - Assert.AreEqual(ModeratedTypeEnum.BlackListed, repo.CheckStatus(ModerationEntityTypeEnum.TwitterAccount, "handle")); - Assert.AreEqual(ModeratedTypeEnum.None, repo.CheckStatus(ModerationEntityTypeEnum.TwitterAccount, "handle2")); + Assert.AreEqual( + ModeratedTypeEnum.BlackListed, + repo.CheckStatus(ModerationEntityTypeEnum.TwitterAccount, "handle") + ); + Assert.AreEqual( + ModeratedTypeEnum.None, + repo.CheckStatus(ModerationEntityTypeEnum.TwitterAccount, "handle2") + ); #endregion } @@ -304,8 +380,14 @@ namespace BirdsiteLive.Domain.Tests.Repository var repo = new ModerationRepository(settings); #region Validations - Assert.AreEqual(ModeratedTypeEnum.WhiteListed, repo.CheckStatus(ModerationEntityTypeEnum.Follower, "@me@domain.ext")); - Assert.AreEqual(ModeratedTypeEnum.None, repo.CheckStatus(ModerationEntityTypeEnum.Follower, "@me2@domain.ext")); + Assert.AreEqual( + ModeratedTypeEnum.WhiteListed, + repo.CheckStatus(ModerationEntityTypeEnum.Follower, "@me@domain.ext") + ); + Assert.AreEqual( + ModeratedTypeEnum.None, + repo.CheckStatus(ModerationEntityTypeEnum.Follower, "@me2@domain.ext") + ); #endregion } @@ -323,8 +405,14 @@ namespace BirdsiteLive.Domain.Tests.Repository var repo = new ModerationRepository(settings); #region Validations - Assert.AreEqual(ModeratedTypeEnum.WhiteListed, repo.CheckStatus(ModerationEntityTypeEnum.TwitterAccount, "handle")); - Assert.AreEqual(ModeratedTypeEnum.None, repo.CheckStatus(ModerationEntityTypeEnum.TwitterAccount, "handle2")); + Assert.AreEqual( + ModeratedTypeEnum.WhiteListed, + repo.CheckStatus(ModerationEntityTypeEnum.TwitterAccount, "handle") + ); + Assert.AreEqual( + ModeratedTypeEnum.None, + repo.CheckStatus(ModerationEntityTypeEnum.TwitterAccount, "handle2") + ); #endregion } @@ -338,10 +426,16 @@ namespace BirdsiteLive.Domain.Tests.Repository var repo = new ModerationRepository(settings); #region Validations - Assert.AreEqual(ModeratedTypeEnum.None, repo.CheckStatus(ModerationEntityTypeEnum.Follower, "@handle@domain.ext")); - Assert.AreEqual(ModeratedTypeEnum.None, repo.CheckStatus(ModerationEntityTypeEnum.TwitterAccount, "handle")); + Assert.AreEqual( + ModeratedTypeEnum.None, + repo.CheckStatus(ModerationEntityTypeEnum.Follower, "@handle@domain.ext") + ); + Assert.AreEqual( + ModeratedTypeEnum.None, + repo.CheckStatus(ModerationEntityTypeEnum.TwitterAccount, "handle") + ); #endregion } #endregion } -} \ No newline at end of file +} diff --git a/src/Tests/BirdsiteLive.Domain.Tests/StatusServiceTests.cs b/src/Tests/BirdsiteLive.Domain.Tests/StatusServiceTests.cs index e6178c3..75e2d85 100644 --- a/src/Tests/BirdsiteLive.Domain.Tests/StatusServiceTests.cs +++ b/src/Tests/BirdsiteLive.Domain.Tests/StatusServiceTests.cs @@ -1,6 +1,8 @@ -using System; +using System; + using BirdsiteLive.Common.Settings; using BirdsiteLive.Twitter.Models; + using Microsoft.VisualStudio.TestTools.UnitTesting; namespace BirdsiteLive.Domain.Tests @@ -13,36 +15,33 @@ namespace BirdsiteLive.Domain.Tests #region Ctor public StatusServiceTests() { - _settings = new InstanceSettings - { - Domain = "domain.name" - }; + _settings = new InstanceSettings { Domain = "domain.name" }; } #endregion -// [TestMethod] -// public void ExtractMentionsTest() -// { -// #region Stubs -// var username = "MyUserName"; -// var extractedTweet = new ExtractedTweet -// { -// Id = 124L, -// CreatedAt = DateTime.UtcNow, -// MessageContent = @"Getting ready for the weekend...have a great one everyone! -//⁠ -//Photo by Tim Tronckoe | @timtronckoe -//⁠ -//#archenemy #michaelamott #alissawhitegluz #jeffloomis #danielerlandsson #sharleedangelo⁠" -// }; -// #endregion + // [TestMethod] + // public void ExtractMentionsTest() + // { + // #region Stubs + // var username = "MyUserName"; + // var extractedTweet = new ExtractedTweet + // { + // Id = 124L, + // CreatedAt = DateTime.UtcNow, + // MessageContent = @"Getting ready for the weekend...have a great one everyone! + //⁠ + //Photo by Tim Tronckoe | @timtronckoe + //⁠ + //#archenemy #michaelamott #alissawhitegluz #jeffloomis #danielerlandsson #sharleedangelo⁠" + // }; + // #endregion -// var service = new StatusService(_settings); -// var result = service.GetStatus(username, extractedTweet); + // var service = new StatusService(_settings); + // var result = service.GetStatus(username, extractedTweet); -// #region Validations + // #region Validations -// #endregion -// } + // #endregion + // } } } diff --git a/src/Tests/BirdsiteLive.Domain.Tests/Tools/ModerationRegexParserTests.cs b/src/Tests/BirdsiteLive.Domain.Tests/Tools/ModerationRegexParserTests.cs index 2d780cf..a9e8df4 100644 --- a/src/Tests/BirdsiteLive.Domain.Tests/Tools/ModerationRegexParserTests.cs +++ b/src/Tests/BirdsiteLive.Domain.Tests/Tools/ModerationRegexParserTests.cs @@ -1,5 +1,6 @@ -using BirdsiteLive.Domain.Repository; +using BirdsiteLive.Domain.Repository; using BirdsiteLive.Domain.Tools; + using Microsoft.VisualStudio.TestTools.UnitTesting; namespace BirdsiteLive.Domain.Tests.Tools @@ -14,7 +15,10 @@ namespace BirdsiteLive.Domain.Tests.Tools var pattern = "handle"; #endregion - var regex = ModerationRegexParser.Parse(ModerationEntityTypeEnum.TwitterAccount, pattern); + var regex = ModerationRegexParser.Parse( + ModerationEntityTypeEnum.TwitterAccount, + pattern + ); #region Validations Assert.IsTrue(regex.IsMatch(pattern)); @@ -75,4 +79,4 @@ namespace BirdsiteLive.Domain.Tests.Tools #endregion } } -} \ No newline at end of file +} diff --git a/src/Tests/BirdsiteLive.Domain.Tests/Tools/PatternsParserTests.cs b/src/Tests/BirdsiteLive.Domain.Tests/Tools/PatternsParserTests.cs index 848be99..9e3a131 100644 --- a/src/Tests/BirdsiteLive.Domain.Tests/Tools/PatternsParserTests.cs +++ b/src/Tests/BirdsiteLive.Domain.Tests/Tools/PatternsParserTests.cs @@ -1,5 +1,7 @@ -using System.Linq; +using System.Linq; + using BirdsiteLive.Domain.Tools; + using Microsoft.VisualStudio.TestTools.UnitTesting; namespace BirdsiteLive.Domain.Tests.Tools @@ -146,4 +148,4 @@ namespace BirdsiteLive.Domain.Tests.Tools #endregion } } -} \ No newline at end of file +} diff --git a/src/Tests/BirdsiteLive.Domain.Tests/Tools/StatusExtractorTests.cs b/src/Tests/BirdsiteLive.Domain.Tests/Tools/StatusExtractorTests.cs index a86b56e..8b9fb8f 100644 --- a/src/Tests/BirdsiteLive.Domain.Tests/Tools/StatusExtractorTests.cs +++ b/src/Tests/BirdsiteLive.Domain.Tests/Tools/StatusExtractorTests.cs @@ -1,10 +1,12 @@ -using System; +using System; using System.Linq; + using BirdsiteLive.Common.Settings; using BirdsiteLive.Domain.Tools; -using BirdsiteLive.Twitter.Models; + using Microsoft.Extensions.Logging; using Microsoft.VisualStudio.TestTools.UnitTesting; + using Moq; namespace BirdsiteLive.Domain.Tests.Tools @@ -17,10 +19,7 @@ namespace BirdsiteLive.Domain.Tests.Tools #region Ctor public StatusExtractorTests() { - _settings = new InstanceSettings - { - Domain = "domain.name" - }; + _settings = new InstanceSettings { Domain = "domain.name" }; } #endregion @@ -85,7 +84,11 @@ namespace BirdsiteLive.Domain.Tests.Tools Assert.AreEqual(0, result.tags.Length); Assert.IsTrue(result.content.Contains("Bla!")); - Assert.IsTrue(result.content.Contains(@"https://t.co/L8BpyHgg25")); + Assert.IsTrue( + result.content.Contains( + @"https://t.co/L8BpyHgg25" + ) + ); #endregion } @@ -93,7 +96,8 @@ namespace BirdsiteLive.Domain.Tests.Tools public void Extract_FormatUrl_Long_Test() { #region Stubs - var message = $"Bla!{Environment.NewLine}https://www.eff.org/deeplinks/2020/07/pact-act-not-solution-problem-harmful-online-content"; + var message = + $"Bla!{Environment.NewLine}https://www.eff.org/deeplinks/2020/07/pact-act-not-solution-problem-harmful-online-content"; #endregion #region Mocks @@ -108,7 +112,11 @@ namespace BirdsiteLive.Domain.Tests.Tools Assert.AreEqual(0, result.tags.Length); Assert.IsTrue(result.content.Contains("Bla!")); - Assert.IsTrue(result.content.Contains(@"https://www.eff.org/deeplinks/2020/07/pact-act-not-solution-problem-harmful-online-content")); + Assert.IsTrue( + result.content.Contains( + @"https://www.eff.org/deeplinks/2020/07/pact-act-not-solution-problem-harmful-online-content" + ) + ); #endregion } @@ -131,7 +139,11 @@ namespace BirdsiteLive.Domain.Tests.Tools Assert.AreEqual(0, result.tags.Length); Assert.IsTrue(result.content.Contains("Bla!")); - Assert.IsTrue(result.content.Contains(@"https://www.eff.org/deeplinks/2020/07/pact")); + Assert.IsTrue( + result.content.Contains( + @"https://www.eff.org/deeplinks/2020/07/pact" + ) + ); #endregion } @@ -139,7 +151,8 @@ namespace BirdsiteLive.Domain.Tests.Tools public void Extract_MultiUrls_Test() { #region Stubs - var message = $"https://t.co/L8BpyHgg25 Bla!{Environment.NewLine}https://www.eff.org/deeplinks/2020/07/pact-act-not-solution-problem-harmful-online-content"; + var message = + $"https://t.co/L8BpyHgg25 Bla!{Environment.NewLine}https://www.eff.org/deeplinks/2020/07/pact-act-not-solution-problem-harmful-online-content"; #endregion #region Mocks @@ -154,9 +167,17 @@ namespace BirdsiteLive.Domain.Tests.Tools Assert.AreEqual(0, result.tags.Length); Assert.IsTrue(result.content.Contains("Bla!")); - Assert.IsTrue(result.content.Contains(@"https://t.co/L8BpyHgg25")); + Assert.IsTrue( + result.content.Contains( + @"https://t.co/L8BpyHgg25" + ) + ); - Assert.IsTrue(result.content.Contains(@"https://www.eff.org/deeplinks/2020/07/pact-act-not-solution-problem-harmful-online-content")); + Assert.IsTrue( + result.content.Contains( + @"https://www.eff.org/deeplinks/2020/07/pact-act-not-solution-problem-harmful-online-content" + ) + ); #endregion } @@ -175,7 +196,10 @@ namespace BirdsiteLive.Domain.Tests.Tools var result = service.Extract(message); #region Validations - Assert.AreEqual(@"🚀 test http://GOV.UK date 🎉 data http://GOV.UK woopsi.", result.content); + Assert.AreEqual( + @"🚀 test http://GOV.UK date 🎉 data http://GOV.UK woopsi.", + result.content + ); #endregion } @@ -194,7 +218,10 @@ namespace BirdsiteLive.Domain.Tests.Tools var result = service.Extract(message); #region Validations - Assert.AreEqual(@"🚀http://GOV.UK", result.content); + Assert.AreEqual( + @"🚀http://GOV.UK", + result.content + ); #endregion } @@ -213,7 +240,10 @@ namespace BirdsiteLive.Domain.Tests.Tools var result = service.Extract(message); #region Validations - Assert.AreEqual(@"🚀http://GOV.UK.", result.content); + Assert.AreEqual( + @"🚀http://GOV.UK.", + result.content + ); #endregion } @@ -232,7 +262,10 @@ namespace BirdsiteLive.Domain.Tests.Tools var result = service.Extract(message); #region Validations - Assert.AreEqual(@"🐣 juniors & tech(http://tech.guru maker)", result.content); + Assert.AreEqual( + @"🐣 juniors & tech(http://tech.guru maker)", + result.content + ); #endregion } @@ -258,7 +291,11 @@ namespace BirdsiteLive.Domain.Tests.Tools Assert.AreEqual("https://domain.name/tags/mytag", result.tags.First().href); Assert.IsTrue(result.content.Contains("Bla!")); - Assert.IsTrue(result.content.Contains(@"#mytag")); + Assert.IsTrue( + result.content.Contains( + @"#mytag" + ) + ); #endregion } @@ -284,7 +321,11 @@ namespace BirdsiteLive.Domain.Tests.Tools Assert.AreEqual("https://domain.name/tags/mytag", result.tags.First().href); Assert.IsTrue(result.content.Contains("Bla!")); - Assert.IsTrue(result.content.Contains(@"#mytag")); + Assert.IsTrue( + result.content.Contains( + @"#mytag" + ) + ); #endregion } @@ -310,7 +351,11 @@ namespace BirdsiteLive.Domain.Tests.Tools Assert.AreEqual("https://domain.name/tags/COVID_19", result.tags.First().href); Assert.IsTrue(result.content.Contains("Bla!")); - Assert.IsTrue(result.content.Contains(@"#COVID_19")); + Assert.IsTrue( + result.content.Contains( + @"#COVID_19" + ) + ); #endregion } @@ -318,7 +363,8 @@ namespace BirdsiteLive.Domain.Tests.Tools public void Extract_MultiHashTags_Test() { #region Stubs - var message = $"Bla!{Environment.NewLine}#mytag #mytag2 #mytag3{Environment.NewLine}Test #bal Test"; + var message = + $"Bla!{Environment.NewLine}#mytag #mytag2 #mytag3{Environment.NewLine}Test #bal Test"; #endregion #region Mocks @@ -332,10 +378,26 @@ namespace BirdsiteLive.Domain.Tests.Tools logger.VerifyAll(); Assert.AreEqual(4, result.tags.Length); Assert.IsTrue(result.content.Contains("Bla!")); - Assert.IsTrue(result.content.Contains(@"#mytag")); - Assert.IsTrue(result.content.Contains(@"#mytag2")); - Assert.IsTrue(result.content.Contains(@"#mytag3")); - Assert.IsTrue(result.content.Contains(@"#bal")); + Assert.IsTrue( + result.content.Contains( + @"#mytag" + ) + ); + Assert.IsTrue( + result.content.Contains( + @"#mytag2" + ) + ); + Assert.IsTrue( + result.content.Contains( + @"#mytag3" + ) + ); + Assert.IsTrue( + result.content.Contains( + @"#bal" + ) + ); #endregion } @@ -361,7 +423,11 @@ namespace BirdsiteLive.Domain.Tests.Tools Assert.AreEqual("https://domain.name/users/mynickname", result.tags.First().href); Assert.IsTrue(result.content.Contains("Bla!")); - Assert.IsTrue(result.content.Contains(@"@mynickname")); + Assert.IsTrue( + result.content.Contains( + @"@mynickname" + ) + ); #endregion } @@ -369,7 +435,8 @@ namespace BirdsiteLive.Domain.Tests.Tools public void Extract_MultiMentionTag_MultiOccurrence_Test() { #region Stubs - var message = $"[RT @yamenbousrih]{Environment.NewLine}@KiwixOffline @photos_floues Bla. Cc @Pyb75 @photos_floues @KiwixOffline"; + var message = + $"[RT @yamenbousrih]{Environment.NewLine}@KiwixOffline @photos_floues Bla. Cc @Pyb75 @photos_floues @KiwixOffline"; #endregion #region Mocks @@ -384,9 +451,21 @@ namespace BirdsiteLive.Domain.Tests.Tools Assert.AreEqual(4, result.tags.Length); Assert.AreEqual("Mention", result.tags.First().type); - Assert.IsTrue(result.content.Contains(@"@photos_floues")); - Assert.IsTrue(result.content.Contains(@"@KiwixOffline @photos_floues")); - Assert.IsTrue(result.content.Contains(@"Cc @Pyb75 @photos_floues @KiwixOffline")); + Assert.IsTrue( + result.content.Contains( + @"@photos_floues" + ) + ); + Assert.IsTrue( + result.content.Contains( + @"@KiwixOffline @photos_floues" + ) + ); + Assert.IsTrue( + result.content.Contains( + @"Cc @Pyb75 @photos_floues @KiwixOffline" + ) + ); #endregion } @@ -412,7 +491,11 @@ namespace BirdsiteLive.Domain.Tests.Tools Assert.AreEqual("https://domain.name/users/mynickname", result.tags.First().href); Assert.IsTrue(result.content.Contains("Bla!")); - Assert.IsTrue(result.content.Contains(@"@mynickname")); + Assert.IsTrue( + result.content.Contains( + @"@mynickname" + ) + ); #endregion } @@ -439,7 +522,11 @@ namespace BirdsiteLive.Domain.Tests.Tools Assert.IsTrue(result.content.Contains("Bla!")); Assert.IsTrue(result.content.Contains("Blo")); - Assert.IsTrue(result.content.Contains(@"@mynickname")); + Assert.IsTrue( + result.content.Contains( + @"@mynickname" + ) + ); #endregion } @@ -465,7 +552,11 @@ namespace BirdsiteLive.Domain.Tests.Tools Assert.AreEqual("https://domain.name/users/my___nickname", result.tags.First().href); Assert.IsTrue(result.content.Contains("Bla!")); - Assert.IsTrue(result.content.Contains(@"@my___nickname")); + Assert.IsTrue( + result.content.Contains( + @"@my___nickname" + ) + ); #endregion } @@ -491,15 +582,20 @@ namespace BirdsiteLive.Domain.Tests.Tools Assert.AreEqual("https://domain.name/users/mynickname", result.tags.First().href); Assert.IsTrue(result.content.Contains("Bla!")); - Assert.IsTrue(result.content.Contains(@"@mynickname")); + Assert.IsTrue( + result.content.Contains( + @"@mynickname" + ) + ); #endregion } - + [TestMethod] public void Extract_MultiMentionTag_Test() { #region Stubs - var message = $"Bla!{Environment.NewLine}@mynickname⁠ @mynickname2 @mynickname3{Environment.NewLine}Test @dada Test"; + var message = + $"Bla!{Environment.NewLine}@mynickname⁠ @mynickname2 @mynickname3{Environment.NewLine}Test @dada Test"; #endregion #region Mocks @@ -513,10 +609,26 @@ namespace BirdsiteLive.Domain.Tests.Tools logger.VerifyAll(); Assert.AreEqual(4, result.tags.Length); Assert.IsTrue(result.content.Contains("Bla!")); - Assert.IsTrue(result.content.Contains(@"@mynickname")); - Assert.IsTrue(result.content.Contains(@"@mynickname2")); - Assert.IsTrue(result.content.Contains(@"@mynickname3")); - Assert.IsTrue(result.content.Contains(@"@dada")); + Assert.IsTrue( + result.content.Contains( + @"@mynickname" + ) + ); + Assert.IsTrue( + result.content.Contains( + @"@mynickname2" + ) + ); + Assert.IsTrue( + result.content.Contains( + @"@mynickname3" + ) + ); + Assert.IsTrue( + result.content.Contains( + @"@dada" + ) + ); #endregion } @@ -524,7 +636,8 @@ namespace BirdsiteLive.Domain.Tests.Tools public void Extract_HeterogeneousTag_Test() { #region Stubs - var message = $"Bla!{Environment.NewLine}@mynickname⁠ #mytag2 @mynickname3{Environment.NewLine}Test @dada #dada Test"; + var message = + $"Bla!{Environment.NewLine}@mynickname⁠ #mytag2 @mynickname3{Environment.NewLine}Test @dada #dada Test"; #endregion #region Mocks @@ -538,14 +651,34 @@ namespace BirdsiteLive.Domain.Tests.Tools logger.VerifyAll(); Assert.AreEqual(5, result.tags.Length); Assert.IsTrue(result.content.Contains("Bla!")); - Assert.IsTrue(result.content.Contains(@"@mynickname")); - Assert.IsTrue(result.content.Contains(@"#mytag2")); - Assert.IsTrue(result.content.Contains(@"@mynickname3")); - Assert.IsTrue(result.content.Contains(@"@dada")); - Assert.IsTrue(result.content.Contains(@"#dada")); + Assert.IsTrue( + result.content.Contains( + @"@mynickname" + ) + ); + Assert.IsTrue( + result.content.Contains( + @"#mytag2" + ) + ); + Assert.IsTrue( + result.content.Contains( + @"@mynickname3" + ) + ); + Assert.IsTrue( + result.content.Contains( + @"@dada" + ) + ); + Assert.IsTrue( + result.content.Contains( + @"#dada" + ) + ); #endregion } - + [TestMethod] public void Extract_Emoji_Test() { @@ -564,8 +697,11 @@ namespace BirdsiteLive.Domain.Tests.Tools #region Validations logger.VerifyAll(); Assert.AreEqual(1, result.tags.Length); - Assert.IsTrue(result.content.Contains( - @"😤@mynickname")); + Assert.IsTrue( + result.content.Contains( + @"😤@mynickname" + ) + ); Assert.IsTrue(result.content.Contains(@"😎😍🤗🤩😘")); #endregion @@ -589,8 +725,12 @@ namespace BirdsiteLive.Domain.Tests.Tools #region Validations logger.VerifyAll(); Assert.AreEqual(1, result.tags.Length); - Assert.IsTrue(result.content.Equals(@"bla (@mynickname test)")); + Assert.IsTrue( + result.content.Equals( + @"bla (@mynickname test)" + ) + ); #endregion } } -} \ No newline at end of file +} diff --git a/src/Tests/BirdsiteLive.Moderation.Tests/Actions/RejectAllFollowingsActionTests.cs b/src/Tests/BirdsiteLive.Moderation.Tests/Actions/RejectAllFollowingsActionTests.cs index 3ed5c78..e73f354 100644 --- a/src/Tests/BirdsiteLive.Moderation.Tests/Actions/RejectAllFollowingsActionTests.cs +++ b/src/Tests/BirdsiteLive.Moderation.Tests/Actions/RejectAllFollowingsActionTests.cs @@ -1,13 +1,16 @@ -using System; +using System; using System.Collections.Generic; using System.Threading.Tasks; + using BirdsiteLive.ActivityPub; using BirdsiteLive.Common.Settings; using BirdsiteLive.DAL.Contracts; using BirdsiteLive.DAL.Models; using BirdsiteLive.Domain; using BirdsiteLive.Moderation.Actions; + using Microsoft.VisualStudio.TestTools.UnitTesting; + using Moq; namespace BirdsiteLive.Moderation.Tests.Actions @@ -21,40 +24,36 @@ namespace BirdsiteLive.Moderation.Tests.Actions #region Stubs var follower = new Follower { - Followings = new List - { - 24 - }, + Followings = new List { 24 }, Host = "host" }; - var settings = new InstanceSettings - { - Domain = "domain" - }; + var settings = new InstanceSettings { Domain = "domain" }; #endregion #region Mocks var twitterUserDalMock = new Mock(MockBehavior.Strict); twitterUserDalMock - .Setup(x => x.GetTwitterUserAsync( - It.Is(y => y == 24))) - .ReturnsAsync(new SyncTwitterUser - { - Id = 24, - Acct = "acct" - }); + .Setup(x => x.GetTwitterUserAsync(It.Is(y => y == 24))) + .ReturnsAsync(new SyncTwitterUser { Id = 24, Acct = "acct" }); var userServiceMock = new Mock(MockBehavior.Strict); userServiceMock - .Setup(x => x.SendRejectFollowAsync( - It.Is(y => y.type == "Follow"), - It.IsNotNull() - )) + .Setup( + x => + x.SendRejectFollowAsync( + It.Is(y => y.type == "Follow"), + It.IsNotNull() + ) + ) .ReturnsAsync(true); #endregion - var action = new RejectAllFollowingsAction(twitterUserDalMock.Object, userServiceMock.Object, settings); + var action = new RejectAllFollowingsAction( + twitterUserDalMock.Object, + userServiceMock.Object, + settings + ); await action.ProcessAsync(follower); #region Validations @@ -69,40 +68,36 @@ namespace BirdsiteLive.Moderation.Tests.Actions #region Stubs var follower = new Follower { - Followings = new List - { - 24 - }, + Followings = new List { 24 }, Host = "host" }; - var settings = new InstanceSettings - { - Domain = "domain" - }; + var settings = new InstanceSettings { Domain = "domain" }; #endregion #region Mocks var twitterUserDalMock = new Mock(MockBehavior.Strict); twitterUserDalMock - .Setup(x => x.GetTwitterUserAsync( - It.Is(y => y == 24))) - .ReturnsAsync(new SyncTwitterUser - { - Id = 24, - Acct = "acct" - }); + .Setup(x => x.GetTwitterUserAsync(It.Is(y => y == 24))) + .ReturnsAsync(new SyncTwitterUser { Id = 24, Acct = "acct" }); var userServiceMock = new Mock(MockBehavior.Strict); userServiceMock - .Setup(x => x.SendRejectFollowAsync( - It.Is(y => y.type == "Follow"), - It.IsNotNull() - )) + .Setup( + x => + x.SendRejectFollowAsync( + It.Is(y => y.type == "Follow"), + It.IsNotNull() + ) + ) .Throws(new Exception()); #endregion - var action = new RejectAllFollowingsAction(twitterUserDalMock.Object, userServiceMock.Object, settings); + var action = new RejectAllFollowingsAction( + twitterUserDalMock.Object, + userServiceMock.Object, + settings + ); await action.ProcessAsync(follower); #region Validations @@ -111,4 +106,4 @@ namespace BirdsiteLive.Moderation.Tests.Actions #endregion } } -} \ No newline at end of file +} diff --git a/src/Tests/BirdsiteLive.Moderation.Tests/Actions/RejectFollowingActionTests.cs b/src/Tests/BirdsiteLive.Moderation.Tests/Actions/RejectFollowingActionTests.cs index 74f037e..75ee9a9 100644 --- a/src/Tests/BirdsiteLive.Moderation.Tests/Actions/RejectFollowingActionTests.cs +++ b/src/Tests/BirdsiteLive.Moderation.Tests/Actions/RejectFollowingActionTests.cs @@ -1,12 +1,15 @@ -using System; +using System; using System.Collections.Generic; using System.Threading.Tasks; + using BirdsiteLive.ActivityPub; using BirdsiteLive.Common.Settings; using BirdsiteLive.DAL.Models; using BirdsiteLive.Domain; using BirdsiteLive.Moderation.Actions; + using Microsoft.VisualStudio.TestTools.UnitTesting; + using Moq; namespace BirdsiteLive.Moderation.Tests.Actions @@ -20,32 +23,25 @@ namespace BirdsiteLive.Moderation.Tests.Actions #region Stubs var follower = new Follower { - Followings = new List - { - 24 - }, + Followings = new List { 24 }, Host = "host" }; - var settings = new InstanceSettings - { - Domain = "domain" - }; + var settings = new InstanceSettings { Domain = "domain" }; - var twitterUser = new SyncTwitterUser - { - Id = 24, - Acct = "acct" - }; + var twitterUser = new SyncTwitterUser { Id = 24, Acct = "acct" }; #endregion #region Mocks var userServiceMock = new Mock(MockBehavior.Strict); userServiceMock - .Setup(x => x.SendRejectFollowAsync( - It.Is(y => y.type == "Follow"), - It.IsNotNull() - )) + .Setup( + x => + x.SendRejectFollowAsync( + It.Is(y => y.type == "Follow"), + It.IsNotNull() + ) + ) .ReturnsAsync(true); #endregion @@ -63,32 +59,25 @@ namespace BirdsiteLive.Moderation.Tests.Actions #region Stubs var follower = new Follower { - Followings = new List - { - 24 - }, + Followings = new List { 24 }, Host = "host" }; - var settings = new InstanceSettings - { - Domain = "domain" - }; + var settings = new InstanceSettings { Domain = "domain" }; - var twitterUser = new SyncTwitterUser - { - Id = 24, - Acct = "acct" - }; + var twitterUser = new SyncTwitterUser { Id = 24, Acct = "acct" }; #endregion #region Mocks var userServiceMock = new Mock(MockBehavior.Strict); userServiceMock - .Setup(x => x.SendRejectFollowAsync( - It.Is(y => y.type == "Follow"), - It.IsNotNull() - )) + .Setup( + x => + x.SendRejectFollowAsync( + It.Is(y => y.type == "Follow"), + It.IsNotNull() + ) + ) .Throws(new Exception()); #endregion @@ -100,4 +89,4 @@ namespace BirdsiteLive.Moderation.Tests.Actions #endregion } } -} \ No newline at end of file +} diff --git a/src/Tests/BirdsiteLive.Moderation.Tests/Actions/RemoveFollowerActionTests.cs b/src/Tests/BirdsiteLive.Moderation.Tests/Actions/RemoveFollowerActionTests.cs index 3b83739..225bdbd 100644 --- a/src/Tests/BirdsiteLive.Moderation.Tests/Actions/RemoveFollowerActionTests.cs +++ b/src/Tests/BirdsiteLive.Moderation.Tests/Actions/RemoveFollowerActionTests.cs @@ -1,9 +1,12 @@ -using System.Collections.Generic; +using System.Collections.Generic; using System.Threading.Tasks; + using BirdsiteLive.DAL.Contracts; using BirdsiteLive.DAL.Models; using BirdsiteLive.Moderation.Actions; + using Microsoft.VisualStudio.TestTools.UnitTesting; + using Moq; namespace BirdsiteLive.Moderation.Tests.Actions @@ -23,31 +26,33 @@ namespace BirdsiteLive.Moderation.Tests.Actions #endregion #region Mocks - var rejectAllFollowingsActionMock = new Mock(MockBehavior.Strict); + var rejectAllFollowingsActionMock = new Mock( + MockBehavior.Strict + ); rejectAllFollowingsActionMock - .Setup(x => x.ProcessAsync( - It.Is(y => y.Id == follower.Id))) + .Setup(x => x.ProcessAsync(It.Is(y => y.Id == follower.Id))) .Returns(Task.CompletedTask); var followersDalMock = new Mock(MockBehavior.Strict); followersDalMock - .Setup(x => x.GetFollowersAsync( - It.Is(y => y == 1))) - .ReturnsAsync(new[] {follower}); + .Setup(x => x.GetFollowersAsync(It.Is(y => y == 1))) + .ReturnsAsync(new[] { follower }); followersDalMock - .Setup(x => x.DeleteFollowerAsync( - It.Is(y => y == 12))) + .Setup(x => x.DeleteFollowerAsync(It.Is(y => y == 12))) .Returns(Task.CompletedTask); var twitterUserDalMock = new Mock(MockBehavior.Strict); twitterUserDalMock - .Setup(x => x.DeleteTwitterUserAsync( - It.Is(y => y == 1))) + .Setup(x => x.DeleteTwitterUserAsync(It.Is(y => y == 1))) .Returns(Task.CompletedTask); #endregion - var action = new RemoveFollowerAction(followersDalMock.Object, twitterUserDalMock.Object, rejectAllFollowingsActionMock.Object); + var action = new RemoveFollowerAction( + followersDalMock.Object, + twitterUserDalMock.Object, + rejectAllFollowingsActionMock.Object + ); await action.ProcessAsync(follower); #region Validations @@ -70,35 +75,35 @@ namespace BirdsiteLive.Moderation.Tests.Actions var followers = new List { follower, - new Follower - { - Id = 11 - } + new Follower { Id = 11 } }; #endregion #region Mocks - var rejectAllFollowingsActionMock = new Mock(MockBehavior.Strict); + var rejectAllFollowingsActionMock = new Mock( + MockBehavior.Strict + ); rejectAllFollowingsActionMock - .Setup(x => x.ProcessAsync( - It.Is(y => y.Id == follower.Id))) + .Setup(x => x.ProcessAsync(It.Is(y => y.Id == follower.Id))) .Returns(Task.CompletedTask); var followersDalMock = new Mock(MockBehavior.Strict); followersDalMock - .Setup(x => x.GetFollowersAsync( - It.Is(y => y == 1))) + .Setup(x => x.GetFollowersAsync(It.Is(y => y == 1))) .ReturnsAsync(followers.ToArray()); followersDalMock - .Setup(x => x.DeleteFollowerAsync( - It.Is(y => y == 12))) + .Setup(x => x.DeleteFollowerAsync(It.Is(y => y == 12))) .Returns(Task.CompletedTask); var twitterUserDalMock = new Mock(MockBehavior.Strict); #endregion - var action = new RemoveFollowerAction(followersDalMock.Object, twitterUserDalMock.Object, rejectAllFollowingsActionMock.Object); + var action = new RemoveFollowerAction( + followersDalMock.Object, + twitterUserDalMock.Object, + rejectAllFollowingsActionMock.Object + ); await action.ProcessAsync(follower); #region Validations @@ -108,4 +113,4 @@ namespace BirdsiteLive.Moderation.Tests.Actions #endregion } } -} \ No newline at end of file +} diff --git a/src/Tests/BirdsiteLive.Moderation.Tests/Actions/RemoveTwitterAccountActionTests.cs b/src/Tests/BirdsiteLive.Moderation.Tests/Actions/RemoveTwitterAccountActionTests.cs index c0f5920..9783bb4 100644 --- a/src/Tests/BirdsiteLive.Moderation.Tests/Actions/RemoveTwitterAccountActionTests.cs +++ b/src/Tests/BirdsiteLive.Moderation.Tests/Actions/RemoveTwitterAccountActionTests.cs @@ -1,9 +1,12 @@ -using System.Collections.Generic; +using System.Collections.Generic; using System.Threading.Tasks; + using BirdsiteLive.DAL.Contracts; using BirdsiteLive.DAL.Models; using BirdsiteLive.Moderation.Actions; + using Microsoft.VisualStudio.TestTools.UnitTesting; + using Moq; namespace BirdsiteLive.Moderation.Tests.Actions @@ -15,18 +18,14 @@ namespace BirdsiteLive.Moderation.Tests.Actions public async Task ProcessAsync_RemoveFollower() { #region Stubs - var twitter = new SyncTwitterUser - { - Id = 24, - Acct = "my-acct" - }; + var twitter = new SyncTwitterUser { Id = 24, Acct = "my-acct" }; var followers = new List { new Follower { Id = 48, - Followings = new List{ 24 }, + Followings = new List { 24 }, FollowingsSyncStatus = new Dictionary { { 24, 1024 } } } }; @@ -35,30 +34,35 @@ namespace BirdsiteLive.Moderation.Tests.Actions #region Mocks var followersDalMock = new Mock(MockBehavior.Strict); followersDalMock - .Setup(x => x.GetFollowersAsync( - It.Is(y => y == 24))) + .Setup(x => x.GetFollowersAsync(It.Is(y => y == 24))) .ReturnsAsync(followers.ToArray()); followersDalMock - .Setup(x => x.DeleteFollowerAsync( - It.Is(y => y == 48))) + .Setup(x => x.DeleteFollowerAsync(It.Is(y => y == 48))) .Returns(Task.CompletedTask); var twitterUserDalMock = new Mock(MockBehavior.Strict); twitterUserDalMock - .Setup(x => x.DeleteTwitterUserAsync( - It.Is(y => y == 24))) + .Setup(x => x.DeleteTwitterUserAsync(It.Is(y => y == 24))) .Returns(Task.CompletedTask); var rejectFollowingActionMock = new Mock(MockBehavior.Strict); rejectFollowingActionMock - .Setup(x => x.ProcessAsync( - It.Is(y => y.Id == 48), - It.Is(y => y.Acct == twitter.Acct))) + .Setup( + x => + x.ProcessAsync( + It.Is(y => y.Id == 48), + It.Is(y => y.Acct == twitter.Acct) + ) + ) .Returns(Task.CompletedTask); #endregion - var action = new RemoveTwitterAccountAction(followersDalMock.Object, twitterUserDalMock.Object, rejectFollowingActionMock.Object); + var action = new RemoveTwitterAccountAction( + followersDalMock.Object, + twitterUserDalMock.Object, + rejectFollowingActionMock.Object + ); await action.ProcessAsync(twitter); #region Validations @@ -72,18 +76,14 @@ namespace BirdsiteLive.Moderation.Tests.Actions public async Task ProcessAsync_KeepFollower() { #region Stubs - var twitter = new SyncTwitterUser - { - Id = 24, - Acct = "my-acct" - }; + var twitter = new SyncTwitterUser { Id = 24, Acct = "my-acct" }; var followers = new List { new Follower { Id = 48, - Followings = new List{ 24, 36 }, + Followings = new List { 24, 36 }, FollowingsSyncStatus = new Dictionary { { 24, 1024 }, { 36, 24 } } } }; @@ -92,33 +92,45 @@ namespace BirdsiteLive.Moderation.Tests.Actions #region Mocks var followersDalMock = new Mock(MockBehavior.Strict); followersDalMock - .Setup(x => x.GetFollowersAsync( - It.Is(y => y == 24))) + .Setup(x => x.GetFollowersAsync(It.Is(y => y == 24))) .ReturnsAsync(followers.ToArray()); followersDalMock - .Setup(x => x.UpdateFollowerAsync( - It.Is(y => y.Id == 48 - && y.Followings.Count == 1 - && y.FollowingsSyncStatus.Count == 1 - ))) + .Setup( + x => + x.UpdateFollowerAsync( + It.Is( + y => + y.Id == 48 + && y.Followings.Count == 1 + && y.FollowingsSyncStatus.Count == 1 + ) + ) + ) .Returns(Task.CompletedTask); var twitterUserDalMock = new Mock(MockBehavior.Strict); twitterUserDalMock - .Setup(x => x.DeleteTwitterUserAsync( - It.Is(y => y == 24))) + .Setup(x => x.DeleteTwitterUserAsync(It.Is(y => y == 24))) .Returns(Task.CompletedTask); var rejectFollowingActionMock = new Mock(MockBehavior.Strict); rejectFollowingActionMock - .Setup(x => x.ProcessAsync( - It.Is(y => y.Id == 48), - It.Is(y => y.Acct == twitter.Acct))) + .Setup( + x => + x.ProcessAsync( + It.Is(y => y.Id == 48), + It.Is(y => y.Acct == twitter.Acct) + ) + ) .Returns(Task.CompletedTask); #endregion - var action = new RemoveTwitterAccountAction(followersDalMock.Object, twitterUserDalMock.Object, rejectFollowingActionMock.Object); + var action = new RemoveTwitterAccountAction( + followersDalMock.Object, + twitterUserDalMock.Object, + rejectFollowingActionMock.Object + ); await action.ProcessAsync(twitter); #region Validations @@ -128,4 +140,4 @@ namespace BirdsiteLive.Moderation.Tests.Actions #endregion } } -} \ No newline at end of file +} diff --git a/src/Tests/BirdsiteLive.Moderation.Tests/BirdsiteLive.Moderation.Tests.csproj b/src/Tests/BirdsiteLive.Moderation.Tests/BirdsiteLive.Moderation.Tests.csproj index e85b592..fbf2e90 100644 --- a/src/Tests/BirdsiteLive.Moderation.Tests/BirdsiteLive.Moderation.Tests.csproj +++ b/src/Tests/BirdsiteLive.Moderation.Tests/BirdsiteLive.Moderation.Tests.csproj @@ -1,7 +1,7 @@ - netcoreapp3.1 + net6.0 false diff --git a/src/Tests/BirdsiteLive.Moderation.Tests/ModerationPipelineTests.cs b/src/Tests/BirdsiteLive.Moderation.Tests/ModerationPipelineTests.cs index 7928b34..51f352f 100644 --- a/src/Tests/BirdsiteLive.Moderation.Tests/ModerationPipelineTests.cs +++ b/src/Tests/BirdsiteLive.Moderation.Tests/ModerationPipelineTests.cs @@ -1,9 +1,12 @@ using System; using System.Threading.Tasks; + using BirdsiteLive.Domain.Repository; using BirdsiteLive.Moderation.Processors; + using Microsoft.Extensions.Logging; using Microsoft.VisualStudio.TestTools.UnitTesting; + using Moq; namespace BirdsiteLive.Moderation.Tests @@ -22,13 +25,21 @@ namespace BirdsiteLive.Moderation.Tests moderationRepositoryMock .Setup(x => x.GetModerationType(ModerationEntityTypeEnum.TwitterAccount)) .Returns(ModerationTypeEnum.None); - - var followerModerationProcessorMock = new Mock(MockBehavior.Strict); - var twitterAccountModerationProcessorMock = new Mock(MockBehavior.Strict); + + var followerModerationProcessorMock = new Mock( + MockBehavior.Strict + ); + var twitterAccountModerationProcessorMock = + new Mock(MockBehavior.Strict); var loggerMock = new Mock>(MockBehavior.Strict); #endregion - var pipeline = new ModerationPipeline(moderationRepositoryMock.Object, followerModerationProcessorMock.Object, twitterAccountModerationProcessorMock.Object, loggerMock.Object); + var pipeline = new ModerationPipeline( + moderationRepositoryMock.Object, + followerModerationProcessorMock.Object, + twitterAccountModerationProcessorMock.Object, + loggerMock.Object + ); await pipeline.ApplyModerationSettingsAsync(); #region Validations @@ -51,22 +62,38 @@ namespace BirdsiteLive.Moderation.Tests .Setup(x => x.GetModerationType(ModerationEntityTypeEnum.TwitterAccount)) .Returns(ModerationTypeEnum.BlackListing); - var followerModerationProcessorMock = new Mock(MockBehavior.Strict); + var followerModerationProcessorMock = new Mock( + MockBehavior.Strict + ); followerModerationProcessorMock - .Setup(x => x.ProcessAsync( - It.Is(y => y == ModerationTypeEnum.WhiteListing))) + .Setup( + x => + x.ProcessAsync( + It.Is(y => y == ModerationTypeEnum.WhiteListing) + ) + ) .Returns(Task.CompletedTask); - var twitterAccountModerationProcessorMock = new Mock(MockBehavior.Strict); + var twitterAccountModerationProcessorMock = + new Mock(MockBehavior.Strict); twitterAccountModerationProcessorMock - .Setup(x => x.ProcessAsync( - It.Is(y => y == ModerationTypeEnum.BlackListing))) + .Setup( + x => + x.ProcessAsync( + It.Is(y => y == ModerationTypeEnum.BlackListing) + ) + ) .Returns(Task.CompletedTask); var loggerMock = new Mock>(MockBehavior.Strict); #endregion - var pipeline = new ModerationPipeline(moderationRepositoryMock.Object, followerModerationProcessorMock.Object, twitterAccountModerationProcessorMock.Object, loggerMock.Object); + var pipeline = new ModerationPipeline( + moderationRepositoryMock.Object, + followerModerationProcessorMock.Object, + twitterAccountModerationProcessorMock.Object, + loggerMock.Object + ); await pipeline.ApplyModerationSettingsAsync(); #region Validations @@ -86,13 +113,21 @@ namespace BirdsiteLive.Moderation.Tests .Setup(x => x.GetModerationType(ModerationEntityTypeEnum.Follower)) .Throws(new Exception()); - var followerModerationProcessorMock = new Mock(MockBehavior.Strict); - var twitterAccountModerationProcessorMock = new Mock(MockBehavior.Strict); - + var followerModerationProcessorMock = new Mock( + MockBehavior.Strict + ); + var twitterAccountModerationProcessorMock = + new Mock(MockBehavior.Strict); + var loggerMock = new Mock>(); #endregion - var pipeline = new ModerationPipeline(moderationRepositoryMock.Object, followerModerationProcessorMock.Object, twitterAccountModerationProcessorMock.Object, loggerMock.Object); + var pipeline = new ModerationPipeline( + moderationRepositoryMock.Object, + followerModerationProcessorMock.Object, + twitterAccountModerationProcessorMock.Object, + loggerMock.Object + ); await pipeline.ApplyModerationSettingsAsync(); #region Validations diff --git a/src/Tests/BirdsiteLive.Moderation.Tests/Processors/FollowerModerationProcessorTests.cs b/src/Tests/BirdsiteLive.Moderation.Tests/Processors/FollowerModerationProcessorTests.cs index 3bc4946..1d54223 100644 --- a/src/Tests/BirdsiteLive.Moderation.Tests/Processors/FollowerModerationProcessorTests.cs +++ b/src/Tests/BirdsiteLive.Moderation.Tests/Processors/FollowerModerationProcessorTests.cs @@ -1,12 +1,16 @@ -using System.Collections.Generic; +using System.Collections.Generic; using System.Threading.Tasks; + using BirdsiteLive.DAL.Contracts; using BirdsiteLive.DAL.Models; using BirdsiteLive.Domain.Repository; using BirdsiteLive.Moderation.Actions; using BirdsiteLive.Moderation.Processors; + using Castle.DynamicProxy.Generators.Emitters; + using Microsoft.VisualStudio.TestTools.UnitTesting; + using Moq; namespace BirdsiteLive.Moderation.Tests.Processors @@ -23,7 +27,11 @@ namespace BirdsiteLive.Moderation.Tests.Processors var removeFollowerActionMock = new Mock(MockBehavior.Strict); #endregion - var processor = new FollowerModerationProcessor(followersDalMock.Object, moderationRepositoryMock.Object, removeFollowerActionMock.Object); + var processor = new FollowerModerationProcessor( + followersDalMock.Object, + moderationRepositoryMock.Object, + removeFollowerActionMock.Object + ); await processor.ProcessAsync(ModerationTypeEnum.None); #region Validations @@ -39,11 +47,7 @@ namespace BirdsiteLive.Moderation.Tests.Processors #region Stubs var allFollowers = new List { - new Follower - { - Acct = "acct", - Host = "host" - } + new Follower { Acct = "acct", Host = "host" } }; #endregion @@ -55,15 +59,25 @@ namespace BirdsiteLive.Moderation.Tests.Processors var moderationRepositoryMock = new Mock(MockBehavior.Strict); moderationRepositoryMock - .Setup(x => x.CheckStatus( - It.Is(y => y == ModerationEntityTypeEnum.Follower), - It.Is(y => y == "@acct@host"))) + .Setup( + x => + x.CheckStatus( + It.Is( + y => y == ModerationEntityTypeEnum.Follower + ), + It.Is(y => y == "@acct@host") + ) + ) .Returns(ModeratedTypeEnum.WhiteListed); var removeFollowerActionMock = new Mock(MockBehavior.Strict); #endregion - var processor = new FollowerModerationProcessor(followersDalMock.Object, moderationRepositoryMock.Object, removeFollowerActionMock.Object); + var processor = new FollowerModerationProcessor( + followersDalMock.Object, + moderationRepositoryMock.Object, + removeFollowerActionMock.Object + ); await processor.ProcessAsync(ModerationTypeEnum.WhiteListing); #region Validations @@ -79,11 +93,7 @@ namespace BirdsiteLive.Moderation.Tests.Processors #region Stubs var allFollowers = new List { - new Follower - { - Acct = "acct", - Host = "host" - } + new Follower { Acct = "acct", Host = "host" } }; #endregion @@ -95,19 +105,28 @@ namespace BirdsiteLive.Moderation.Tests.Processors var moderationRepositoryMock = new Mock(MockBehavior.Strict); moderationRepositoryMock - .Setup(x => x.CheckStatus( - It.Is(y => y == ModerationEntityTypeEnum.Follower), - It.Is(y => y == "@acct@host"))) + .Setup( + x => + x.CheckStatus( + It.Is( + y => y == ModerationEntityTypeEnum.Follower + ), + It.Is(y => y == "@acct@host") + ) + ) .Returns(ModeratedTypeEnum.None); var removeFollowerActionMock = new Mock(MockBehavior.Strict); removeFollowerActionMock - .Setup(x => x.ProcessAsync( - It.Is(y => y.Acct == "acct"))) + .Setup(x => x.ProcessAsync(It.Is(y => y.Acct == "acct"))) .Returns(Task.CompletedTask); #endregion - var processor = new FollowerModerationProcessor(followersDalMock.Object, moderationRepositoryMock.Object, removeFollowerActionMock.Object); + var processor = new FollowerModerationProcessor( + followersDalMock.Object, + moderationRepositoryMock.Object, + removeFollowerActionMock.Object + ); await processor.ProcessAsync(ModerationTypeEnum.WhiteListing); #region Validations @@ -123,11 +142,7 @@ namespace BirdsiteLive.Moderation.Tests.Processors #region Stubs var allFollowers = new List { - new Follower - { - Acct = "acct", - Host = "host" - } + new Follower { Acct = "acct", Host = "host" } }; #endregion @@ -139,19 +154,28 @@ namespace BirdsiteLive.Moderation.Tests.Processors var moderationRepositoryMock = new Mock(MockBehavior.Strict); moderationRepositoryMock - .Setup(x => x.CheckStatus( - It.Is(y => y == ModerationEntityTypeEnum.Follower), - It.Is(y => y == "@acct@host"))) + .Setup( + x => + x.CheckStatus( + It.Is( + y => y == ModerationEntityTypeEnum.Follower + ), + It.Is(y => y == "@acct@host") + ) + ) .Returns(ModeratedTypeEnum.BlackListed); var removeFollowerActionMock = new Mock(MockBehavior.Strict); removeFollowerActionMock - .Setup(x => x.ProcessAsync( - It.Is(y => y.Acct == "acct"))) + .Setup(x => x.ProcessAsync(It.Is(y => y.Acct == "acct"))) .Returns(Task.CompletedTask); #endregion - var processor = new FollowerModerationProcessor(followersDalMock.Object, moderationRepositoryMock.Object, removeFollowerActionMock.Object); + var processor = new FollowerModerationProcessor( + followersDalMock.Object, + moderationRepositoryMock.Object, + removeFollowerActionMock.Object + ); await processor.ProcessAsync(ModerationTypeEnum.BlackListing); #region Validations @@ -167,11 +191,7 @@ namespace BirdsiteLive.Moderation.Tests.Processors #region Stubs var allFollowers = new List { - new Follower - { - Acct = "acct", - Host = "host" - } + new Follower { Acct = "acct", Host = "host" } }; #endregion @@ -183,15 +203,25 @@ namespace BirdsiteLive.Moderation.Tests.Processors var moderationRepositoryMock = new Mock(MockBehavior.Strict); moderationRepositoryMock - .Setup(x => x.CheckStatus( - It.Is(y => y == ModerationEntityTypeEnum.Follower), - It.Is(y => y == "@acct@host"))) + .Setup( + x => + x.CheckStatus( + It.Is( + y => y == ModerationEntityTypeEnum.Follower + ), + It.Is(y => y == "@acct@host") + ) + ) .Returns(ModeratedTypeEnum.None); var removeFollowerActionMock = new Mock(MockBehavior.Strict); #endregion - var processor = new FollowerModerationProcessor(followersDalMock.Object, moderationRepositoryMock.Object, removeFollowerActionMock.Object); + var processor = new FollowerModerationProcessor( + followersDalMock.Object, + moderationRepositoryMock.Object, + removeFollowerActionMock.Object + ); await processor.ProcessAsync(ModerationTypeEnum.BlackListing); #region Validations @@ -201,4 +231,4 @@ namespace BirdsiteLive.Moderation.Tests.Processors #endregion } } -} \ No newline at end of file +} diff --git a/src/Tests/BirdsiteLive.Moderation.Tests/Processors/TwitterAccountModerationProcessorTests.cs b/src/Tests/BirdsiteLive.Moderation.Tests/Processors/TwitterAccountModerationProcessorTests.cs index 21d1288..60bc7a6 100644 --- a/src/Tests/BirdsiteLive.Moderation.Tests/Processors/TwitterAccountModerationProcessorTests.cs +++ b/src/Tests/BirdsiteLive.Moderation.Tests/Processors/TwitterAccountModerationProcessorTests.cs @@ -1,11 +1,14 @@ -using System.Collections.Generic; +using System.Collections.Generic; using System.Threading.Tasks; + using BirdsiteLive.DAL.Contracts; using BirdsiteLive.DAL.Models; using BirdsiteLive.Domain.Repository; using BirdsiteLive.Moderation.Actions; using BirdsiteLive.Moderation.Processors; + using Microsoft.VisualStudio.TestTools.UnitTesting; + using Moq; namespace BirdsiteLive.Moderation.Tests.Processors @@ -19,10 +22,16 @@ namespace BirdsiteLive.Moderation.Tests.Processors #region Mocks var twitterUserDalMock = new Mock(MockBehavior.Strict); var moderationRepositoryMock = new Mock(MockBehavior.Strict); - var removeTwitterAccountActionMock = new Mock(MockBehavior.Strict); + var removeTwitterAccountActionMock = new Mock( + MockBehavior.Strict + ); #endregion - var processor = new TwitterAccountModerationProcessor(twitterUserDalMock.Object, moderationRepositoryMock.Object, removeTwitterAccountActionMock.Object); + var processor = new TwitterAccountModerationProcessor( + twitterUserDalMock.Object, + moderationRepositoryMock.Object, + removeTwitterAccountActionMock.Object + ); await processor.ProcessAsync(ModerationTypeEnum.None); #region Validations @@ -36,13 +45,7 @@ namespace BirdsiteLive.Moderation.Tests.Processors public async Task ProcessAsync_WhiteListing_WhiteListed() { #region Stubs - var allUsers = new List - { - new SyncTwitterUser - { - Acct = "acct" - } - }; + var allUsers = new List { new SyncTwitterUser { Acct = "acct" } }; #endregion #region Mocks @@ -53,15 +56,27 @@ namespace BirdsiteLive.Moderation.Tests.Processors var moderationRepositoryMock = new Mock(MockBehavior.Strict); moderationRepositoryMock - .Setup(x => x.CheckStatus( - It.Is(y => y == ModerationEntityTypeEnum.TwitterAccount), - It.Is(y => y == "acct"))) + .Setup( + x => + x.CheckStatus( + It.Is( + y => y == ModerationEntityTypeEnum.TwitterAccount + ), + It.Is(y => y == "acct") + ) + ) .Returns(ModeratedTypeEnum.WhiteListed); - var removeTwitterAccountActionMock = new Mock(MockBehavior.Strict); + var removeTwitterAccountActionMock = new Mock( + MockBehavior.Strict + ); #endregion - var processor = new TwitterAccountModerationProcessor(twitterUserDalMock.Object, moderationRepositoryMock.Object, removeTwitterAccountActionMock.Object); + var processor = new TwitterAccountModerationProcessor( + twitterUserDalMock.Object, + moderationRepositoryMock.Object, + removeTwitterAccountActionMock.Object + ); await processor.ProcessAsync(ModerationTypeEnum.WhiteListing); #region Validations @@ -75,13 +90,7 @@ namespace BirdsiteLive.Moderation.Tests.Processors public async Task ProcessAsync_WhiteListing_NotWhiteListed() { #region Stubs - var allUsers = new List - { - new SyncTwitterUser - { - Acct = "acct" - } - }; + var allUsers = new List { new SyncTwitterUser { Acct = "acct" } }; #endregion #region Mocks @@ -92,19 +101,30 @@ namespace BirdsiteLive.Moderation.Tests.Processors var moderationRepositoryMock = new Mock(MockBehavior.Strict); moderationRepositoryMock - .Setup(x => x.CheckStatus( - It.Is(y => y == ModerationEntityTypeEnum.TwitterAccount), - It.Is(y => y == "acct"))) + .Setup( + x => + x.CheckStatus( + It.Is( + y => y == ModerationEntityTypeEnum.TwitterAccount + ), + It.Is(y => y == "acct") + ) + ) .Returns(ModeratedTypeEnum.None); - var removeTwitterAccountActionMock = new Mock(MockBehavior.Strict); + var removeTwitterAccountActionMock = new Mock( + MockBehavior.Strict + ); removeTwitterAccountActionMock - .Setup(x => x.ProcessAsync( - It.Is(y => y.Acct == "acct"))) + .Setup(x => x.ProcessAsync(It.Is(y => y.Acct == "acct"))) .Returns(Task.CompletedTask); #endregion - var processor = new TwitterAccountModerationProcessor(twitterUserDalMock.Object, moderationRepositoryMock.Object, removeTwitterAccountActionMock.Object); + var processor = new TwitterAccountModerationProcessor( + twitterUserDalMock.Object, + moderationRepositoryMock.Object, + removeTwitterAccountActionMock.Object + ); await processor.ProcessAsync(ModerationTypeEnum.WhiteListing); #region Validations @@ -118,13 +138,7 @@ namespace BirdsiteLive.Moderation.Tests.Processors public async Task ProcessAsync_BlackListing_BlackListed() { #region Stubs - var allUsers = new List - { - new SyncTwitterUser - { - Acct = "acct" - } - }; + var allUsers = new List { new SyncTwitterUser { Acct = "acct" } }; #endregion #region Mocks @@ -135,19 +149,30 @@ namespace BirdsiteLive.Moderation.Tests.Processors var moderationRepositoryMock = new Mock(MockBehavior.Strict); moderationRepositoryMock - .Setup(x => x.CheckStatus( - It.Is(y => y == ModerationEntityTypeEnum.TwitterAccount), - It.Is(y => y == "acct"))) + .Setup( + x => + x.CheckStatus( + It.Is( + y => y == ModerationEntityTypeEnum.TwitterAccount + ), + It.Is(y => y == "acct") + ) + ) .Returns(ModeratedTypeEnum.BlackListed); - var removeTwitterAccountActionMock = new Mock(MockBehavior.Strict); + var removeTwitterAccountActionMock = new Mock( + MockBehavior.Strict + ); removeTwitterAccountActionMock - .Setup(x => x.ProcessAsync( - It.Is(y => y.Acct == "acct"))) + .Setup(x => x.ProcessAsync(It.Is(y => y.Acct == "acct"))) .Returns(Task.CompletedTask); #endregion - var processor = new TwitterAccountModerationProcessor(twitterUserDalMock.Object, moderationRepositoryMock.Object, removeTwitterAccountActionMock.Object); + var processor = new TwitterAccountModerationProcessor( + twitterUserDalMock.Object, + moderationRepositoryMock.Object, + removeTwitterAccountActionMock.Object + ); await processor.ProcessAsync(ModerationTypeEnum.BlackListing); #region Validations @@ -161,13 +186,7 @@ namespace BirdsiteLive.Moderation.Tests.Processors public async Task ProcessAsync_BlackListing_NotBlackListed() { #region Stubs - var allUsers = new List - { - new SyncTwitterUser - { - Acct = "acct" - } - }; + var allUsers = new List { new SyncTwitterUser { Acct = "acct" } }; #endregion #region Mocks @@ -178,15 +197,27 @@ namespace BirdsiteLive.Moderation.Tests.Processors var moderationRepositoryMock = new Mock(MockBehavior.Strict); moderationRepositoryMock - .Setup(x => x.CheckStatus( - It.Is(y => y == ModerationEntityTypeEnum.TwitterAccount), - It.Is(y => y == "acct"))) + .Setup( + x => + x.CheckStatus( + It.Is( + y => y == ModerationEntityTypeEnum.TwitterAccount + ), + It.Is(y => y == "acct") + ) + ) .Returns(ModeratedTypeEnum.None); - var removeTwitterAccountActionMock = new Mock(MockBehavior.Strict); + var removeTwitterAccountActionMock = new Mock( + MockBehavior.Strict + ); #endregion - var processor = new TwitterAccountModerationProcessor(twitterUserDalMock.Object, moderationRepositoryMock.Object, removeTwitterAccountActionMock.Object); + var processor = new TwitterAccountModerationProcessor( + twitterUserDalMock.Object, + moderationRepositoryMock.Object, + removeTwitterAccountActionMock.Object + ); await processor.ProcessAsync(ModerationTypeEnum.BlackListing); #region Validations @@ -196,4 +227,4 @@ namespace BirdsiteLive.Moderation.Tests.Processors #endregion } } -} \ No newline at end of file +} diff --git a/src/Tests/BirdsiteLive.Pipeline.Tests/BirdsiteLive.Pipeline.Tests.csproj b/src/Tests/BirdsiteLive.Pipeline.Tests/BirdsiteLive.Pipeline.Tests.csproj index d1cfd06..9c073aa 100644 --- a/src/Tests/BirdsiteLive.Pipeline.Tests/BirdsiteLive.Pipeline.Tests.csproj +++ b/src/Tests/BirdsiteLive.Pipeline.Tests/BirdsiteLive.Pipeline.Tests.csproj @@ -1,7 +1,7 @@ - netcoreapp3.1 + net6.0 false diff --git a/src/Tests/BirdsiteLive.Pipeline.Tests/Processors/RefreshTwitterUserStatusProcessorTests.cs b/src/Tests/BirdsiteLive.Pipeline.Tests/Processors/RefreshTwitterUserStatusProcessorTests.cs index d5fbeef..45f6815 100644 --- a/src/Tests/BirdsiteLive.Pipeline.Tests/Processors/RefreshTwitterUserStatusProcessorTests.cs +++ b/src/Tests/BirdsiteLive.Pipeline.Tests/Processors/RefreshTwitterUserStatusProcessorTests.cs @@ -1,7 +1,8 @@ -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; + using BirdsiteLive.Common.Settings; using BirdsiteLive.DAL.Contracts; using BirdsiteLive.DAL.Models; @@ -10,7 +11,9 @@ using BirdsiteLive.Pipeline.Models; using BirdsiteLive.Pipeline.Processors; using BirdsiteLive.Twitter; using BirdsiteLive.Twitter.Models; + using Microsoft.VisualStudio.TestTools.UnitTesting; + using Moq; namespace BirdsiteLive.Pipeline.Tests.Processors @@ -27,40 +30,35 @@ namespace BirdsiteLive.Pipeline.Tests.Processors var users = new List { - new SyncTwitterUser - { - Id = userId1 - }, - new SyncTwitterUser - { - Id = userId2 - } + new SyncTwitterUser { Id = userId1 }, + new SyncTwitterUser { Id = userId2 } }; - var settings = new InstanceSettings - { - FailingTwitterUserCleanUpThreshold = 300 - }; + var settings = new InstanceSettings { FailingTwitterUserCleanUpThreshold = 300 }; #endregion #region Mocks var twitterUserServiceMock = new Mock(MockBehavior.Strict); twitterUserServiceMock .Setup(x => x.GetUser(It.IsAny())) - .Returns(new TwitterUser - { - Protected = false - }); + .Returns(new TwitterUser { Protected = false }); var twitterUserDalMock = new Mock(MockBehavior.Strict); - var removeTwitterAccountActionMock = new Mock(MockBehavior.Strict); + var removeTwitterAccountActionMock = new Mock( + MockBehavior.Strict + ); #endregion - var processor = new RefreshTwitterUserStatusProcessor(twitterUserServiceMock.Object, twitterUserDalMock.Object, removeTwitterAccountActionMock.Object, settings); + var processor = new RefreshTwitterUserStatusProcessor( + twitterUserServiceMock.Object, + twitterUserDalMock.Object, + removeTwitterAccountActionMock.Object, + settings + ); var result = await processor.ProcessAsync(users.ToArray(), CancellationToken.None); #region Validations - Assert.AreEqual(2 , result.Length); + Assert.AreEqual(2, result.Length); Assert.IsTrue(result.Any(x => x.User.Id == userId1)); Assert.IsTrue(result.Any(x => x.User.Id == userId2)); @@ -78,33 +76,30 @@ namespace BirdsiteLive.Pipeline.Tests.Processors var users = new List { - new SyncTwitterUser - { - Id = userId1, - FetchingErrorCount = 100 - } + new SyncTwitterUser { Id = userId1, FetchingErrorCount = 100 } }; - var settings = new InstanceSettings - { - FailingTwitterUserCleanUpThreshold = 300 - }; + var settings = new InstanceSettings { FailingTwitterUserCleanUpThreshold = 300 }; #endregion #region Mocks var twitterUserServiceMock = new Mock(MockBehavior.Strict); twitterUserServiceMock .Setup(x => x.GetUser(It.IsAny())) - .Returns(new TwitterUser - { - Protected = false - }); + .Returns(new TwitterUser { Protected = false }); var twitterUserDalMock = new Mock(MockBehavior.Strict); - var removeTwitterAccountActionMock = new Mock(MockBehavior.Strict); + var removeTwitterAccountActionMock = new Mock( + MockBehavior.Strict + ); #endregion - var processor = new RefreshTwitterUserStatusProcessor(twitterUserServiceMock.Object, twitterUserDalMock.Object, removeTwitterAccountActionMock.Object, settings); + var processor = new RefreshTwitterUserStatusProcessor( + twitterUserServiceMock.Object, + twitterUserDalMock.Object, + removeTwitterAccountActionMock.Object, + settings + ); var result = await processor.ProcessAsync(users.ToArray(), CancellationToken.None); #region Validations @@ -130,57 +125,52 @@ namespace BirdsiteLive.Pipeline.Tests.Processors var users = new List { - new SyncTwitterUser - { - Id = userId1, - Acct = acct1 - }, - new SyncTwitterUser - { - Id = userId2, - Acct = acct2 - } + new SyncTwitterUser { Id = userId1, Acct = acct1 }, + new SyncTwitterUser { Id = userId2, Acct = acct2 } }; - var settings = new InstanceSettings - { - FailingTwitterUserCleanUpThreshold = 300 - }; + var settings = new InstanceSettings { FailingTwitterUserCleanUpThreshold = 300 }; #endregion #region Mocks var twitterUserServiceMock = new Mock(MockBehavior.Strict); twitterUserServiceMock .Setup(x => x.GetUser(It.Is(y => y == acct1))) - .Returns(new TwitterUser - { - Protected = false - }); + .Returns(new TwitterUser { Protected = false }); twitterUserServiceMock .Setup(x => x.GetUser(It.Is(y => y == acct2))) - .Returns((TwitterUser) null); + .Returns((TwitterUser)null); - twitterUserServiceMock - .Setup(x => x.PurgeUser(It.Is(y => y == acct2))); + twitterUserServiceMock.Setup(x => x.PurgeUser(It.Is(y => y == acct2))); var twitterUserDalMock = new Mock(MockBehavior.Strict); twitterUserDalMock .Setup(x => x.GetTwitterUserAsync(It.Is(y => y == acct2))) - .ReturnsAsync(new SyncTwitterUser - { - Id = userId2, - FetchingErrorCount = 0 - }); + .ReturnsAsync(new SyncTwitterUser { Id = userId2, FetchingErrorCount = 0 }); twitterUserDalMock - .Setup(x => x.UpdateTwitterUserAsync(It.Is(y => y.Id == userId2 && y.FetchingErrorCount == 1))) + .Setup( + x => + x.UpdateTwitterUserAsync( + It.Is( + y => y.Id == userId2 && y.FetchingErrorCount == 1 + ) + ) + ) .Returns(Task.CompletedTask); - var removeTwitterAccountActionMock = new Mock(MockBehavior.Strict); + var removeTwitterAccountActionMock = new Mock( + MockBehavior.Strict + ); #endregion - var processor = new RefreshTwitterUserStatusProcessor(twitterUserServiceMock.Object, twitterUserDalMock.Object, removeTwitterAccountActionMock.Object, settings); + var processor = new RefreshTwitterUserStatusProcessor( + twitterUserServiceMock.Object, + twitterUserDalMock.Object, + removeTwitterAccountActionMock.Object, + settings + ); var result = await processor.ProcessAsync(users.ToArray(), CancellationToken.None); #region Validations @@ -205,56 +195,44 @@ namespace BirdsiteLive.Pipeline.Tests.Processors var users = new List { - new SyncTwitterUser - { - Id = userId1, - Acct = acct1 - }, - new SyncTwitterUser - { - Id = userId2, - Acct = acct2 - } + new SyncTwitterUser { Id = userId1, Acct = acct1 }, + new SyncTwitterUser { Id = userId2, Acct = acct2 } }; - var settings = new InstanceSettings - { - FailingTwitterUserCleanUpThreshold = 300 - }; + var settings = new InstanceSettings { FailingTwitterUserCleanUpThreshold = 300 }; #endregion #region Mocks var twitterUserServiceMock = new Mock(MockBehavior.Strict); twitterUserServiceMock .Setup(x => x.GetUser(It.Is(y => y == acct1))) - .Returns(new TwitterUser - { - Protected = false - }); + .Returns(new TwitterUser { Protected = false }); twitterUserServiceMock .Setup(x => x.GetUser(It.Is(y => y == acct2))) .Returns((TwitterUser)null); - twitterUserServiceMock - .Setup(x => x.PurgeUser(It.Is(y => y == acct2))); + twitterUserServiceMock.Setup(x => x.PurgeUser(It.Is(y => y == acct2))); var twitterUserDalMock = new Mock(MockBehavior.Strict); twitterUserDalMock .Setup(x => x.GetTwitterUserAsync(It.Is(y => y == acct2))) - .ReturnsAsync(new SyncTwitterUser - { - Id = userId2, - FetchingErrorCount = 500 - }); + .ReturnsAsync(new SyncTwitterUser { Id = userId2, FetchingErrorCount = 500 }); - var removeTwitterAccountActionMock = new Mock(MockBehavior.Strict); + var removeTwitterAccountActionMock = new Mock( + MockBehavior.Strict + ); removeTwitterAccountActionMock .Setup(x => x.ProcessAsync(It.Is(y => y.Id == userId2))) .Returns(Task.CompletedTask); #endregion - var processor = new RefreshTwitterUserStatusProcessor(twitterUserServiceMock.Object, twitterUserDalMock.Object, removeTwitterAccountActionMock.Object, settings); + var processor = new RefreshTwitterUserStatusProcessor( + twitterUserServiceMock.Object, + twitterUserDalMock.Object, + removeTwitterAccountActionMock.Object, + settings + ); var result = await processor.ProcessAsync(users.ToArray(), CancellationToken.None); #region Validations @@ -279,45 +257,35 @@ namespace BirdsiteLive.Pipeline.Tests.Processors var users = new List { - new SyncTwitterUser - { - Id = userId1, - Acct = acct1 - }, - new SyncTwitterUser - { - Id = userId2, - Acct = acct2 - } + new SyncTwitterUser { Id = userId1, Acct = acct1 }, + new SyncTwitterUser { Id = userId2, Acct = acct2 } }; - var settings = new InstanceSettings - { - FailingTwitterUserCleanUpThreshold = 300 - }; + var settings = new InstanceSettings { FailingTwitterUserCleanUpThreshold = 300 }; #endregion #region Mocks var twitterUserServiceMock = new Mock(MockBehavior.Strict); twitterUserServiceMock .Setup(x => x.GetUser(It.Is(y => y == acct1))) - .Returns(new TwitterUser - { - Protected = false - }); + .Returns(new TwitterUser { Protected = false }); twitterUserServiceMock .Setup(x => x.GetUser(It.Is(y => y == acct2))) - .Returns(new TwitterUser - { - Protected = true - }); + .Returns(new TwitterUser { Protected = true }); var twitterUserDalMock = new Mock(MockBehavior.Strict); - var removeTwitterAccountActionMock = new Mock(MockBehavior.Strict); + var removeTwitterAccountActionMock = new Mock( + MockBehavior.Strict + ); #endregion - var processor = new RefreshTwitterUserStatusProcessor(twitterUserServiceMock.Object, twitterUserDalMock.Object, removeTwitterAccountActionMock.Object, settings); + var processor = new RefreshTwitterUserStatusProcessor( + twitterUserServiceMock.Object, + twitterUserDalMock.Object, + removeTwitterAccountActionMock.Object, + settings + ); var result = await processor.ProcessAsync(users.ToArray(), CancellationToken.None); #region Validations @@ -336,7 +304,7 @@ namespace BirdsiteLive.Pipeline.Tests.Processors #region Stubs var userId1 = 1; var acct1 = "user1"; - + var users = new List { new SyncTwitterUser @@ -349,10 +317,7 @@ namespace BirdsiteLive.Pipeline.Tests.Processors } }; - var settings = new InstanceSettings - { - FailingTwitterUserCleanUpThreshold = 300 - }; + var settings = new InstanceSettings { FailingTwitterUserCleanUpThreshold = 300 }; #endregion #region Mocks @@ -360,9 +325,8 @@ namespace BirdsiteLive.Pipeline.Tests.Processors twitterUserServiceMock .Setup(x => x.GetUser(It.Is(y => y == acct1))) .Returns((TwitterUser)null); - - twitterUserServiceMock - .Setup(x => x.PurgeUser(It.Is(y => y == acct1))); + + twitterUserServiceMock.Setup(x => x.PurgeUser(It.Is(y => y == acct1))); var twitterUserDalMock = new Mock(MockBehavior.Strict); twitterUserDalMock @@ -370,14 +334,30 @@ namespace BirdsiteLive.Pipeline.Tests.Processors .ReturnsAsync(users.First()); twitterUserDalMock - .Setup(x => x.UpdateTwitterUserAsync( - It.Is(y => y.Id == userId1 && y.FetchingErrorCount == 1 && y.LastSync != default))) + .Setup( + x => + x.UpdateTwitterUserAsync( + It.Is( + y => + y.Id == userId1 + && y.FetchingErrorCount == 1 + && y.LastSync != default + ) + ) + ) .Returns(Task.CompletedTask); - var removeTwitterAccountActionMock = new Mock(MockBehavior.Strict); + var removeTwitterAccountActionMock = new Mock( + MockBehavior.Strict + ); #endregion - var processor = new RefreshTwitterUserStatusProcessor(twitterUserServiceMock.Object, twitterUserDalMock.Object, removeTwitterAccountActionMock.Object, settings); + var processor = new RefreshTwitterUserStatusProcessor( + twitterUserServiceMock.Object, + twitterUserDalMock.Object, + removeTwitterAccountActionMock.Object, + settings + ); var result = await processor.ProcessAsync(users.ToArray(), CancellationToken.None); #region Validations @@ -389,4 +369,4 @@ namespace BirdsiteLive.Pipeline.Tests.Processors #endregion } } -} \ No newline at end of file +} diff --git a/src/Tests/BirdsiteLive.Pipeline.Tests/Processors/RetrieveFollowersProcessorTests.cs b/src/Tests/BirdsiteLive.Pipeline.Tests/Processors/RetrieveFollowersProcessorTests.cs index 4679259..f308dfd 100644 --- a/src/Tests/BirdsiteLive.Pipeline.Tests/Processors/RetrieveFollowersProcessorTests.cs +++ b/src/Tests/BirdsiteLive.Pipeline.Tests/Processors/RetrieveFollowersProcessorTests.cs @@ -1,12 +1,15 @@ -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; + using BirdsiteLive.DAL.Contracts; using BirdsiteLive.DAL.Models; using BirdsiteLive.Pipeline.Models; using BirdsiteLive.Pipeline.Processors; + using Microsoft.VisualStudio.TestTools.UnitTesting; + using Moq; namespace BirdsiteLive.Pipeline.Tests.Processors @@ -23,27 +26,11 @@ namespace BirdsiteLive.Pipeline.Tests.Processors var users = new List { - new UserWithDataToSync - { - User = new SyncTwitterUser - { - Id = userId1 - } - }, - new UserWithDataToSync - { - User = new SyncTwitterUser - { - Id = userId2 - } - } + new UserWithDataToSync { User = new SyncTwitterUser { Id = userId1 } }, + new UserWithDataToSync { User = new SyncTwitterUser { Id = userId2 } } }; - var followersUser1 = new List - { - new Follower(), - new Follower(), - }; + var followersUser1 = new List { new Follower(), new Follower(), }; var followersUser2 = new List { new Follower(), @@ -64,7 +51,9 @@ namespace BirdsiteLive.Pipeline.Tests.Processors #endregion var processor = new RetrieveFollowersProcessor(followersDalMock.Object); - var result = (await processor.ProcessAsync(users.ToArray(), CancellationToken.None)).ToList(); + var result = ( + await processor.ProcessAsync(users.ToArray(), CancellationToken.None) + ).ToList(); #region Validations Assert.IsNotNull(result); @@ -76,4 +65,4 @@ namespace BirdsiteLive.Pipeline.Tests.Processors #endregion } } -} \ No newline at end of file +} diff --git a/src/Tests/BirdsiteLive.Pipeline.Tests/Processors/RetrieveTweetsProcessorTests.cs b/src/Tests/BirdsiteLive.Pipeline.Tests/Processors/RetrieveTweetsProcessorTests.cs index 17a3aa2..da224c3 100644 --- a/src/Tests/BirdsiteLive.Pipeline.Tests/Processors/RetrieveTweetsProcessorTests.cs +++ b/src/Tests/BirdsiteLive.Pipeline.Tests/Processors/RetrieveTweetsProcessorTests.cs @@ -2,14 +2,17 @@ using System; using System.Linq; using System.Threading; using System.Threading.Tasks; + using BirdsiteLive.DAL.Contracts; using BirdsiteLive.DAL.Models; using BirdsiteLive.Pipeline.Models; using BirdsiteLive.Pipeline.Processors; using BirdsiteLive.Twitter; using BirdsiteLive.Twitter.Models; + using Microsoft.Extensions.Logging; using Microsoft.VisualStudio.TestTools.UnitTesting; + using Moq; namespace BirdsiteLive.Pipeline.Tests.Processors @@ -28,44 +31,38 @@ namespace BirdsiteLive.Pipeline.Tests.Processors LastTweetPostedId = -1 }; - var user1WtData = new UserWithDataToSync - { - User = user1, - }; + var user1WtData = new UserWithDataToSync { User = user1, }; - var users = new[] - { - user1WtData - }; + var users = new[] { user1WtData }; - var tweets = new[] - { - new ExtractedTweet - { - Id = 47 - } - }; + var tweets = new[] { new ExtractedTweet { Id = 47 } }; #endregion #region Mocks var twitterServiceMock = new Mock(MockBehavior.Strict); twitterServiceMock - .Setup(x => x.GetTimeline( - It.Is(y => y == user1.Acct), - It.Is(y => y == 1), - It.Is(y => y == -1) - )) + .Setup( + x => + x.GetTimeline( + It.Is(y => y == user1.Acct), + It.Is(y => y == 1), + It.Is(y => y == -1) + ) + ) .Returns(tweets); var twitterUserDalMock = new Mock(MockBehavior.Strict); twitterUserDalMock - .Setup(x => x.UpdateTwitterUserAsync( - It.Is(y => y == user1.Id), - It.Is(y => y == tweets.Last().Id), - It.Is(y => y == tweets.Last().Id), - It.Is(y => y == 0), - It.IsAny() - )) + .Setup( + x => + x.UpdateTwitterUserAsync( + It.Is(y => y == user1.Id), + It.Is(y => y == tweets.Last().Id), + It.Is(y => y == tweets.Last().Id), + It.Is(y => y == 0), + It.IsAny() + ) + ) .Returns(Task.CompletedTask); var twitterUserServiceMock = new Mock(MockBehavior.Strict); @@ -73,7 +70,12 @@ namespace BirdsiteLive.Pipeline.Tests.Processors var logger = new Mock>(MockBehavior.Strict); #endregion - var processor = new RetrieveTweetsProcessor(twitterServiceMock.Object, twitterUserDalMock.Object, twitterUserServiceMock.Object, logger.Object); + var processor = new RetrieveTweetsProcessor( + twitterServiceMock.Object, + twitterUserDalMock.Object, + twitterUserServiceMock.Object, + logger.Object + ); var usersResult = await processor.ProcessAsync(users, CancellationToken.None); #region Validations @@ -98,41 +100,29 @@ namespace BirdsiteLive.Pipeline.Tests.Processors LastTweetSynchronizedForAllFollowersId = 46 }; - var user1WtData = new UserWithDataToSync - { - User = user1, - }; + var user1WtData = new UserWithDataToSync { User = user1, }; - var users = new[] - { - user1WtData - }; + var users = new[] { user1WtData }; var tweets = new[] { - new ExtractedTweet - { - Id = 47 - }, - new ExtractedTweet - { - Id = 48 - }, - new ExtractedTweet - { - Id = 49 - } + new ExtractedTweet { Id = 47 }, + new ExtractedTweet { Id = 48 }, + new ExtractedTweet { Id = 49 } }; #endregion #region Mocks var twitterServiceMock = new Mock(MockBehavior.Strict); twitterServiceMock - .Setup(x => x.GetTimeline( - It.Is(y => y == user1.Acct), - It.Is(y => y == 200), - It.Is(y => y == user1.LastTweetSynchronizedForAllFollowersId) - )) + .Setup( + x => + x.GetTimeline( + It.Is(y => y == user1.Acct), + It.Is(y => y == 200), + It.Is(y => y == user1.LastTweetSynchronizedForAllFollowersId) + ) + ) .Returns(tweets); var twitterUserDalMock = new Mock(MockBehavior.Strict); @@ -142,7 +132,12 @@ namespace BirdsiteLive.Pipeline.Tests.Processors var logger = new Mock>(MockBehavior.Strict); #endregion - var processor = new RetrieveTweetsProcessor(twitterServiceMock.Object, twitterUserDalMock.Object, twitterUserServiceMock.Object, logger.Object); + var processor = new RetrieveTweetsProcessor( + twitterServiceMock.Object, + twitterUserDalMock.Object, + twitterUserServiceMock.Object, + logger.Object + ); var usersResult = await processor.ProcessAsync(users, CancellationToken.None); #region Validations @@ -151,7 +146,6 @@ namespace BirdsiteLive.Pipeline.Tests.Processors twitterUserServiceMock.VerifyAll(); logger.VerifyAll(); - Assert.AreEqual(users.Length, usersResult.Length); Assert.AreEqual(users[0].User.Acct, usersResult[0].User.Acct); Assert.AreEqual(tweets.Length, usersResult[0].Tweets.Length); @@ -170,41 +164,29 @@ namespace BirdsiteLive.Pipeline.Tests.Processors LastTweetSynchronizedForAllFollowersId = 46 }; - var user1WtData = new UserWithDataToSync - { - User = user1, - }; + var user1WtData = new UserWithDataToSync { User = user1, }; - var users = new[] - { - user1WtData - }; + var users = new[] { user1WtData }; var tweets = new[] { - new ExtractedTweet - { - Id = 47 - }, - new ExtractedTweet - { - Id = 48 - }, - new ExtractedTweet - { - Id = 49 - } + new ExtractedTweet { Id = 47 }, + new ExtractedTweet { Id = 48 }, + new ExtractedTweet { Id = 49 } }; #endregion #region Mocks var twitterServiceMock = new Mock(MockBehavior.Strict); twitterServiceMock - .Setup(x => x.GetTimeline( - It.Is(y => y == user1.Acct), - It.Is(y => y == 200), - It.Is(y => y == user1.LastTweetSynchronizedForAllFollowersId) - )) + .Setup( + x => + x.GetTimeline( + It.Is(y => y == user1.Acct), + It.Is(y => y == 200), + It.Is(y => y == user1.LastTweetSynchronizedForAllFollowersId) + ) + ) .Returns(tweets); var twitterUserDalMock = new Mock(MockBehavior.Strict); @@ -214,7 +196,12 @@ namespace BirdsiteLive.Pipeline.Tests.Processors var logger = new Mock>(MockBehavior.Strict); #endregion - var processor = new RetrieveTweetsProcessor(twitterServiceMock.Object, twitterUserDalMock.Object, twitterUserServiceMock.Object, logger.Object); + var processor = new RetrieveTweetsProcessor( + twitterServiceMock.Object, + twitterUserDalMock.Object, + twitterUserServiceMock.Object, + logger.Object + ); var usersResult = await processor.ProcessAsync(users, CancellationToken.None); #region Validations @@ -229,4 +216,4 @@ namespace BirdsiteLive.Pipeline.Tests.Processors #endregion } } -} \ No newline at end of file +} diff --git a/src/Tests/BirdsiteLive.Pipeline.Tests/Processors/RetrieveTwitterUsersProcessorTests.cs b/src/Tests/BirdsiteLive.Pipeline.Tests/Processors/RetrieveTwitterUsersProcessorTests.cs index 4d0e465..60d6a1d 100644 --- a/src/Tests/BirdsiteLive.Pipeline.Tests/Processors/RetrieveTwitterUsersProcessorTests.cs +++ b/src/Tests/BirdsiteLive.Pipeline.Tests/Processors/RetrieveTwitterUsersProcessorTests.cs @@ -1,15 +1,18 @@ -using System; +using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using System.Threading.Tasks.Dataflow; + using BirdsiteLive.Common.Settings; using BirdsiteLive.DAL.Contracts; using BirdsiteLive.DAL.Models; using BirdsiteLive.Pipeline.Processors; using BirdsiteLive.Pipeline.Tools; + using Microsoft.Extensions.Logging; using Microsoft.VisualStudio.TestTools.UnitTesting; + using Moq; namespace BirdsiteLive.Pipeline.Tests.Processors @@ -39,14 +42,17 @@ namespace BirdsiteLive.Pipeline.Tests.Processors var twitterUserDalMock = new Mock(MockBehavior.Strict); twitterUserDalMock - .Setup(x => x.GetAllTwitterUsersAsync( - It.Is(y => y == maxUsers))) + .Setup(x => x.GetAllTwitterUsersAsync(It.Is(y => y == maxUsers))) .ReturnsAsync(users); - + var loggerMock = new Mock>(); #endregion - var processor = new RetrieveTwitterUsersProcessor(twitterUserDalMock.Object, maxUsersNumberProviderMock.Object, loggerMock.Object); + var processor = new RetrieveTwitterUsersProcessor( + twitterUserDalMock.Object, + maxUsersNumberProviderMock.Object, + loggerMock.Object + ); processor.WaitFactor = 10; var t = processor.GetTwitterUsersAsync(buffer, CancellationToken.None); @@ -82,8 +88,7 @@ namespace BirdsiteLive.Pipeline.Tests.Processors var twitterUserDalMock = new Mock(MockBehavior.Strict); twitterUserDalMock - .SetupSequence(x => x.GetAllTwitterUsersAsync( - It.Is(y => y == maxUsers))) + .SetupSequence(x => x.GetAllTwitterUsersAsync(It.Is(y => y == maxUsers))) .ReturnsAsync(users.ToArray()) .ReturnsAsync(new SyncTwitterUser[0]) .ReturnsAsync(new SyncTwitterUser[0]) @@ -93,12 +98,16 @@ namespace BirdsiteLive.Pipeline.Tests.Processors var loggerMock = new Mock>(); #endregion - var processor = new RetrieveTwitterUsersProcessor(twitterUserDalMock.Object, maxUsersNumberProviderMock.Object, loggerMock.Object); + var processor = new RetrieveTwitterUsersProcessor( + twitterUserDalMock.Object, + maxUsersNumberProviderMock.Object, + loggerMock.Object + ); processor.WaitFactor = 2; var t = processor.GetTwitterUsersAsync(buffer, CancellationToken.None); await Task.WhenAny(t, Task.Delay(300)); - + #region Validations maxUsersNumberProviderMock.VerifyAll(); twitterUserDalMock.VerifyAll(); @@ -129,18 +138,21 @@ namespace BirdsiteLive.Pipeline.Tests.Processors var twitterUserDalMock = new Mock(MockBehavior.Strict); twitterUserDalMock - .SetupSequence(x => x.GetAllTwitterUsersAsync( - It.Is(y => y == maxUsers))) + .SetupSequence(x => x.GetAllTwitterUsersAsync(It.Is(y => y == maxUsers))) .ReturnsAsync(users.ToArray()) .ReturnsAsync(new SyncTwitterUser[0]) .ReturnsAsync(new SyncTwitterUser[0]) .ReturnsAsync(new SyncTwitterUser[0]) .ReturnsAsync(new SyncTwitterUser[0]); - + var loggerMock = new Mock>(); #endregion - var processor = new RetrieveTwitterUsersProcessor(twitterUserDalMock.Object, maxUsersNumberProviderMock.Object, loggerMock.Object); + var processor = new RetrieveTwitterUsersProcessor( + twitterUserDalMock.Object, + maxUsersNumberProviderMock.Object, + loggerMock.Object + ); processor.WaitFactor = 2; var t = processor.GetTwitterUsersAsync(buffer, CancellationToken.None); var t2 = Task.Run(async () => @@ -177,16 +189,19 @@ namespace BirdsiteLive.Pipeline.Tests.Processors var twitterUserDalMock = new Mock(MockBehavior.Strict); twitterUserDalMock - .Setup(x => x.GetAllTwitterUsersAsync( - It.Is(y => y == maxUsers))) + .Setup(x => x.GetAllTwitterUsersAsync(It.Is(y => y == maxUsers))) .ReturnsAsync(new SyncTwitterUser[0]); var loggerMock = new Mock>(); #endregion - var processor = new RetrieveTwitterUsersProcessor(twitterUserDalMock.Object, maxUsersNumberProviderMock.Object, loggerMock.Object); + var processor = new RetrieveTwitterUsersProcessor( + twitterUserDalMock.Object, + maxUsersNumberProviderMock.Object, + loggerMock.Object + ); processor.WaitFactor = 1; - var t =processor.GetTwitterUsersAsync(buffer, CancellationToken.None); + var t = processor.GetTwitterUsersAsync(buffer, CancellationToken.None); await Task.WhenAny(t, Task.Delay(50)); @@ -196,7 +211,7 @@ namespace BirdsiteLive.Pipeline.Tests.Processors Assert.AreEqual(0, buffer.Count); #endregion } - + [TestMethod] public async Task GetTwitterUsersAsync_Exception_Test() { @@ -214,14 +229,17 @@ namespace BirdsiteLive.Pipeline.Tests.Processors var twitterUserDalMock = new Mock(MockBehavior.Strict); twitterUserDalMock - .Setup(x => x.GetAllTwitterUsersAsync( - It.Is(y => y == maxUsers))) + .Setup(x => x.GetAllTwitterUsersAsync(It.Is(y => y == maxUsers))) .Returns(async () => await DelayFaultedTask(new Exception())); var loggerMock = new Mock>(); #endregion - var processor = new RetrieveTwitterUsersProcessor(twitterUserDalMock.Object, maxUsersNumberProviderMock.Object, loggerMock.Object); + var processor = new RetrieveTwitterUsersProcessor( + twitterUserDalMock.Object, + maxUsersNumberProviderMock.Object, + loggerMock.Object + ); processor.WaitFactor = 10; var t = processor.GetTwitterUsersAsync(buffer, CancellationToken.None); @@ -253,11 +271,15 @@ namespace BirdsiteLive.Pipeline.Tests.Processors .ReturnsAsync(maxUsers); var twitterUserDalMock = new Mock(MockBehavior.Strict); - + var loggerMock = new Mock>(); #endregion - var processor = new RetrieveTwitterUsersProcessor(twitterUserDalMock.Object, maxUsersNumberProviderMock.Object, loggerMock.Object); + var processor = new RetrieveTwitterUsersProcessor( + twitterUserDalMock.Object, + maxUsersNumberProviderMock.Object, + loggerMock.Object + ); processor.WaitFactor = 1; await processor.GetTwitterUsersAsync(buffer, canTokenS.Token); } @@ -268,4 +290,4 @@ namespace BirdsiteLive.Pipeline.Tests.Processors throw e; } } -} \ No newline at end of file +} diff --git a/src/Tests/BirdsiteLive.Pipeline.Tests/Processors/SaveProgressionProcessorTests.cs b/src/Tests/BirdsiteLive.Pipeline.Tests/Processors/SaveProgressionProcessorTests.cs index 4587071..0e76fb0 100644 --- a/src/Tests/BirdsiteLive.Pipeline.Tests/Processors/SaveProgressionProcessorTests.cs +++ b/src/Tests/BirdsiteLive.Pipeline.Tests/Processors/SaveProgressionProcessorTests.cs @@ -1,15 +1,19 @@ -using System; +using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; + using BirdsiteLive.DAL.Contracts; using BirdsiteLive.DAL.Models; using BirdsiteLive.Pipeline.Models; using BirdsiteLive.Pipeline.Processors; using BirdsiteLive.Twitter.Models; + using Castle.DynamicProxy.Contributors; + using Microsoft.Extensions.Logging; using Microsoft.VisualStudio.TestTools.UnitTesting; + using Moq; namespace BirdsiteLive.Pipeline.Tests.Processors @@ -21,37 +25,18 @@ namespace BirdsiteLive.Pipeline.Tests.Processors public async Task ProcessAsync_Test() { #region Stubs - var user = new SyncTwitterUser - { - Id = 1 - }; - var tweet1 = new ExtractedTweet - { - Id = 36 - }; - var tweet2 = new ExtractedTweet - { - Id = 37 - }; + var user = new SyncTwitterUser { Id = 1 }; + var tweet1 = new ExtractedTweet { Id = 36 }; + var tweet2 = new ExtractedTweet { Id = 37 }; var follower1 = new Follower { - FollowingsSyncStatus = new Dictionary - { - {1, 37} - } + FollowingsSyncStatus = new Dictionary { { 1, 37 } } }; var usersWithTweets = new UserWithDataToSync { - Tweets = new [] - { - tweet1, - tweet2 - }, - Followers = new [] - { - follower1 - }, + Tweets = new[] { tweet1, tweet2 }, + Followers = new[] { follower1 }, User = user }; @@ -61,17 +46,23 @@ namespace BirdsiteLive.Pipeline.Tests.Processors #region Mocks var twitterUserDalMock = new Mock(MockBehavior.Strict); twitterUserDalMock - .Setup(x => x.UpdateTwitterUserAsync( - It.Is(y => y == user.Id), - It.Is(y => y == tweet2.Id), - It.Is(y => y == tweet2.Id), - It.Is(y => y == 0), - It.IsAny() - )) + .Setup( + x => + x.UpdateTwitterUserAsync( + It.Is(y => y == user.Id), + It.Is(y => y == tweet2.Id), + It.Is(y => y == tweet2.Id), + It.Is(y => y == 0), + It.IsAny() + ) + ) .Returns(Task.CompletedTask); #endregion - var processor = new SaveProgressionProcessor(twitterUserDalMock.Object, loggerMock.Object); + var processor = new SaveProgressionProcessor( + twitterUserDalMock.Object, + loggerMock.Object + ); await processor.ProcessAsync(usersWithTweets, CancellationToken.None); #region Validations @@ -84,42 +75,19 @@ namespace BirdsiteLive.Pipeline.Tests.Processors public async Task ProcessAsync_PartiallySynchronized_Test() { #region Stubs - var user = new SyncTwitterUser - { - Id = 1 - }; - var tweet1 = new ExtractedTweet - { - Id = 36 - }; - var tweet2 = new ExtractedTweet - { - Id = 37 - }; - var tweet3 = new ExtractedTweet - { - Id = 38 - }; + var user = new SyncTwitterUser { Id = 1 }; + var tweet1 = new ExtractedTweet { Id = 36 }; + var tweet2 = new ExtractedTweet { Id = 37 }; + var tweet3 = new ExtractedTweet { Id = 38 }; var follower1 = new Follower { - FollowingsSyncStatus = new Dictionary - { - {1, 37} - } + FollowingsSyncStatus = new Dictionary { { 1, 37 } } }; var usersWithTweets = new UserWithDataToSync { - Tweets = new[] - { - tweet1, - tweet2, - tweet3 - }, - Followers = new[] - { - follower1 - }, + Tweets = new[] { tweet1, tweet2, tweet3 }, + Followers = new[] { follower1 }, User = user }; #endregion @@ -127,19 +95,25 @@ namespace BirdsiteLive.Pipeline.Tests.Processors #region Mocks var twitterUserDalMock = new Mock(MockBehavior.Strict); twitterUserDalMock - .Setup(x => x.UpdateTwitterUserAsync( - It.Is(y => y == user.Id), - It.Is(y => y == tweet3.Id), - It.Is(y => y == tweet2.Id), - It.Is(y => y == 0), - It.IsAny() - )) + .Setup( + x => + x.UpdateTwitterUserAsync( + It.Is(y => y == user.Id), + It.Is(y => y == tweet3.Id), + It.Is(y => y == tweet2.Id), + It.Is(y => y == 0), + It.IsAny() + ) + ) .Returns(Task.CompletedTask); var loggerMock = new Mock>(); #endregion - var processor = new SaveProgressionProcessor(twitterUserDalMock.Object, loggerMock.Object); + var processor = new SaveProgressionProcessor( + twitterUserDalMock.Object, + loggerMock.Object + ); await processor.ProcessAsync(usersWithTweets, CancellationToken.None); #region Validations @@ -152,50 +126,23 @@ namespace BirdsiteLive.Pipeline.Tests.Processors public async Task ProcessAsync_PartiallySynchronized_MultiUsers_Test() { #region Stubs - var user = new SyncTwitterUser - { - Id = 1 - }; - var tweet1 = new ExtractedTweet - { - Id = 36 - }; - var tweet2 = new ExtractedTweet - { - Id = 37 - }; - var tweet3 = new ExtractedTweet - { - Id = 38 - }; + var user = new SyncTwitterUser { Id = 1 }; + var tweet1 = new ExtractedTweet { Id = 36 }; + var tweet2 = new ExtractedTweet { Id = 37 }; + var tweet3 = new ExtractedTweet { Id = 38 }; var follower1 = new Follower { - FollowingsSyncStatus = new Dictionary - { - {1, 37} - } + FollowingsSyncStatus = new Dictionary { { 1, 37 } } }; var follower2 = new Follower { - FollowingsSyncStatus = new Dictionary - { - {1, 38} - } + FollowingsSyncStatus = new Dictionary { { 1, 38 } } }; var usersWithTweets = new UserWithDataToSync { - Tweets = new[] - { - tweet1, - tweet2, - tweet3 - }, - Followers = new[] - { - follower1, - follower2 - }, + Tweets = new[] { tweet1, tweet2, tweet3 }, + Followers = new[] { follower1, follower2 }, User = user }; #endregion @@ -203,19 +150,25 @@ namespace BirdsiteLive.Pipeline.Tests.Processors #region Mocks var twitterUserDalMock = new Mock(MockBehavior.Strict); twitterUserDalMock - .Setup(x => x.UpdateTwitterUserAsync( - It.Is(y => y == user.Id), - It.Is(y => y == tweet3.Id), - It.Is(y => y == tweet2.Id), - It.Is(y => y == 0), - It.IsAny() - )) + .Setup( + x => + x.UpdateTwitterUserAsync( + It.Is(y => y == user.Id), + It.Is(y => y == tweet3.Id), + It.Is(y => y == tweet2.Id), + It.Is(y => y == 0), + It.IsAny() + ) + ) .Returns(Task.CompletedTask); var loggerMock = new Mock>(); #endregion - var processor = new SaveProgressionProcessor(twitterUserDalMock.Object, loggerMock.Object); + var processor = new SaveProgressionProcessor( + twitterUserDalMock.Object, + loggerMock.Object + ); await processor.ProcessAsync(usersWithTweets, CancellationToken.None); #region Validations @@ -224,4 +177,4 @@ namespace BirdsiteLive.Pipeline.Tests.Processors #endregion } } -} \ No newline at end of file +} diff --git a/src/Tests/BirdsiteLive.Pipeline.Tests/Processors/SendTweetsToFollowersProcessorTests.cs b/src/Tests/BirdsiteLive.Pipeline.Tests/Processors/SendTweetsToFollowersProcessorTests.cs index 53aa12a..450bdc5 100644 --- a/src/Tests/BirdsiteLive.Pipeline.Tests/Processors/SendTweetsToFollowersProcessorTests.cs +++ b/src/Tests/BirdsiteLive.Pipeline.Tests/Processors/SendTweetsToFollowersProcessorTests.cs @@ -1,15 +1,18 @@ -using System; +using System; using System.Threading; using System.Threading.Tasks; using System.Xml; + using BirdsiteLive.DAL.Contracts; using BirdsiteLive.DAL.Models; using BirdsiteLive.Pipeline.Models; using BirdsiteLive.Pipeline.Processors; using BirdsiteLive.Pipeline.Processors.SubTasks; using BirdsiteLive.Twitter.Models; + using Microsoft.Extensions.Logging; using Microsoft.VisualStudio.TestTools.UnitTesting; + using Moq; namespace BirdsiteLive.Pipeline.Tests.Processors @@ -30,18 +33,9 @@ namespace BirdsiteLive.Pipeline.Tests.Processors var userWithTweets = new UserWithDataToSync() { - Tweets = new [] - { - new ExtractedTweet - { - Id = tweetId - } - }, - User = new SyncTwitterUser - { - Acct = userAcct - }, - Followers = new [] + Tweets = new[] { new ExtractedTweet { Id = tweetId } }, + User = new SyncTwitterUser { Acct = userAcct }, + Followers = new[] { new Follower { @@ -62,13 +56,19 @@ namespace BirdsiteLive.Pipeline.Tests.Processors #region Mocks var sendTweetsToInboxTaskMock = new Mock(MockBehavior.Strict); - var sendTweetsToSharedInboxTaskMock = new Mock(MockBehavior.Strict); + var sendTweetsToSharedInboxTaskMock = new Mock( + MockBehavior.Strict + ); sendTweetsToSharedInboxTaskMock - .Setup(x => x.ExecuteAsync( - It.Is(y => y.Length == 1), - It.Is(y => y.Acct == userAcct), - It.Is(y => y == host), - It.Is(y => y.Length == 2))) + .Setup( + x => + x.ExecuteAsync( + It.Is(y => y.Length == 1), + It.Is(y => y.Acct == userAcct), + It.Is(y => y == host), + It.Is(y => y.Length == 2) + ) + ) .Returns(Task.CompletedTask); var followersDalMock = new Mock(MockBehavior.Strict); @@ -76,7 +76,12 @@ namespace BirdsiteLive.Pipeline.Tests.Processors var loggerMock = new Mock>(); #endregion - var processor = new SendTweetsToFollowersProcessor(sendTweetsToInboxTaskMock.Object, sendTweetsToSharedInboxTaskMock.Object, followersDalMock.Object, loggerMock.Object); + var processor = new SendTweetsToFollowersProcessor( + sendTweetsToInboxTaskMock.Object, + sendTweetsToSharedInboxTaskMock.Object, + followersDalMock.Object, + loggerMock.Object + ); var result = await processor.ProcessAsync(userWithTweets, CancellationToken.None); #region Validations @@ -100,17 +105,8 @@ namespace BirdsiteLive.Pipeline.Tests.Processors var userWithTweets = new UserWithDataToSync() { - Tweets = new[] - { - new ExtractedTweet - { - Id = tweetId - } - }, - User = new SyncTwitterUser - { - Acct = userAcct - }, + Tweets = new[] { new ExtractedTweet { Id = tweetId } }, + User = new SyncTwitterUser { Acct = userAcct }, Followers = new[] { new Follower @@ -132,24 +128,35 @@ namespace BirdsiteLive.Pipeline.Tests.Processors #region Mocks var sendTweetsToInboxTaskMock = new Mock(MockBehavior.Strict); - var sendTweetsToSharedInboxTaskMock = new Mock(MockBehavior.Strict); - foreach (var host in new [] { host1, host2}) + var sendTweetsToSharedInboxTaskMock = new Mock( + MockBehavior.Strict + ); + foreach (var host in new[] { host1, host2 }) { sendTweetsToSharedInboxTaskMock - .Setup(x => x.ExecuteAsync( - It.Is(y => y.Length == 1), - It.Is(y => y.Acct == userAcct), - It.Is(y => y == host), - It.Is(y => y.Length == 1))) + .Setup( + x => + x.ExecuteAsync( + It.Is(y => y.Length == 1), + It.Is(y => y.Acct == userAcct), + It.Is(y => y == host), + It.Is(y => y.Length == 1) + ) + ) .Returns(Task.CompletedTask); } var followersDalMock = new Mock(MockBehavior.Strict); - + var loggerMock = new Mock>(); #endregion - var processor = new SendTweetsToFollowersProcessor(sendTweetsToInboxTaskMock.Object, sendTweetsToSharedInboxTaskMock.Object, followersDalMock.Object, loggerMock.Object); + var processor = new SendTweetsToFollowersProcessor( + sendTweetsToInboxTaskMock.Object, + sendTweetsToSharedInboxTaskMock.Object, + followersDalMock.Object, + loggerMock.Object + ); var result = await processor.ProcessAsync(userWithTweets, CancellationToken.None); #region Validations @@ -173,17 +180,8 @@ namespace BirdsiteLive.Pipeline.Tests.Processors var userWithTweets = new UserWithDataToSync() { - Tweets = new[] - { - new ExtractedTweet - { - Id = tweetId - } - }, - User = new SyncTwitterUser - { - Acct = userAcct - }, + Tweets = new[] { new ExtractedTweet { Id = tweetId } }, + User = new SyncTwitterUser { Acct = userAcct }, Followers = new[] { new Follower @@ -205,33 +203,53 @@ namespace BirdsiteLive.Pipeline.Tests.Processors #region Mocks var sendTweetsToInboxTaskMock = new Mock(MockBehavior.Strict); - var sendTweetsToSharedInboxTaskMock = new Mock(MockBehavior.Strict); + var sendTweetsToSharedInboxTaskMock = new Mock( + MockBehavior.Strict + ); sendTweetsToSharedInboxTaskMock - .Setup(x => x.ExecuteAsync( - It.Is(y => y.Length == 1), - It.Is(y => y.Acct == userAcct), - It.Is(y => y == host1), - It.Is(y => y.Length == 1))) + .Setup( + x => + x.ExecuteAsync( + It.Is(y => y.Length == 1), + It.Is(y => y.Acct == userAcct), + It.Is(y => y == host1), + It.Is(y => y.Length == 1) + ) + ) .Returns(Task.CompletedTask); sendTweetsToSharedInboxTaskMock - .Setup(x => x.ExecuteAsync( - It.Is(y => y.Length == 1), - It.Is(y => y.Acct == userAcct), - It.Is(y => y == host2), - It.Is(y => y.Length == 1))) + .Setup( + x => + x.ExecuteAsync( + It.Is(y => y.Length == 1), + It.Is(y => y.Acct == userAcct), + It.Is(y => y == host2), + It.Is(y => y.Length == 1) + ) + ) .Throws(new Exception()); var followersDalMock = new Mock(MockBehavior.Strict); - + followersDalMock - .Setup(x => x.UpdateFollowerAsync(It.Is(y => y.Id == userId2 && y.PostingErrorCount == 1))) + .Setup( + x => + x.UpdateFollowerAsync( + It.Is(y => y.Id == userId2 && y.PostingErrorCount == 1) + ) + ) .Returns(Task.CompletedTask); var loggerMock = new Mock>(); #endregion - var processor = new SendTweetsToFollowersProcessor(sendTweetsToInboxTaskMock.Object, sendTweetsToSharedInboxTaskMock.Object, followersDalMock.Object, loggerMock.Object); + var processor = new SendTweetsToFollowersProcessor( + sendTweetsToInboxTaskMock.Object, + sendTweetsToSharedInboxTaskMock.Object, + followersDalMock.Object, + loggerMock.Object + ); var result = await processor.ProcessAsync(userWithTweets, CancellationToken.None); #region Validations @@ -255,17 +273,8 @@ namespace BirdsiteLive.Pipeline.Tests.Processors var userWithTweets = new UserWithDataToSync() { - Tweets = new[] - { - new ExtractedTweet - { - Id = tweetId - } - }, - User = new SyncTwitterUser - { - Acct = userAcct - }, + Tweets = new[] { new ExtractedTweet { Id = tweetId } }, + User = new SyncTwitterUser { Acct = userAcct }, Followers = new[] { new Follower @@ -288,33 +297,53 @@ namespace BirdsiteLive.Pipeline.Tests.Processors #region Mocks var sendTweetsToInboxTaskMock = new Mock(MockBehavior.Strict); - var sendTweetsToSharedInboxTaskMock = new Mock(MockBehavior.Strict); + var sendTweetsToSharedInboxTaskMock = new Mock( + MockBehavior.Strict + ); sendTweetsToSharedInboxTaskMock - .Setup(x => x.ExecuteAsync( - It.Is(y => y.Length == 1), - It.Is(y => y.Acct == userAcct), - It.Is(y => y == host1), - It.Is(y => y.Length == 1))) + .Setup( + x => + x.ExecuteAsync( + It.Is(y => y.Length == 1), + It.Is(y => y.Acct == userAcct), + It.Is(y => y == host1), + It.Is(y => y.Length == 1) + ) + ) .Returns(Task.CompletedTask); sendTweetsToSharedInboxTaskMock - .Setup(x => x.ExecuteAsync( - It.Is(y => y.Length == 1), - It.Is(y => y.Acct == userAcct), - It.Is(y => y == host2), - It.Is(y => y.Length == 1))) + .Setup( + x => + x.ExecuteAsync( + It.Is(y => y.Length == 1), + It.Is(y => y.Acct == userAcct), + It.Is(y => y == host2), + It.Is(y => y.Length == 1) + ) + ) .Returns(Task.CompletedTask); var followersDalMock = new Mock(MockBehavior.Strict); followersDalMock - .Setup(x => x.UpdateFollowerAsync(It.Is(y => y.Id == userId2 && y.PostingErrorCount == 0))) + .Setup( + x => + x.UpdateFollowerAsync( + It.Is(y => y.Id == userId2 && y.PostingErrorCount == 0) + ) + ) .Returns(Task.CompletedTask); var loggerMock = new Mock>(); #endregion - var processor = new SendTweetsToFollowersProcessor(sendTweetsToInboxTaskMock.Object, sendTweetsToSharedInboxTaskMock.Object, followersDalMock.Object, loggerMock.Object); + var processor = new SendTweetsToFollowersProcessor( + sendTweetsToInboxTaskMock.Object, + sendTweetsToSharedInboxTaskMock.Object, + followersDalMock.Object, + loggerMock.Object + ); var result = await processor.ProcessAsync(userWithTweets, CancellationToken.None); #region Validations @@ -338,17 +367,8 @@ namespace BirdsiteLive.Pipeline.Tests.Processors var userWithTweets = new UserWithDataToSync() { - Tweets = new[] - { - new ExtractedTweet - { - Id = tweetId - } - }, - User = new SyncTwitterUser - { - Acct = userAcct - }, + Tweets = new[] { new ExtractedTweet { Id = tweetId } }, + User = new SyncTwitterUser { Acct = userAcct }, Followers = new[] { new Follower @@ -372,37 +392,62 @@ namespace BirdsiteLive.Pipeline.Tests.Processors #region Mocks var sendTweetsToInboxTaskMock = new Mock(MockBehavior.Strict); - var sendTweetsToSharedInboxTaskMock = new Mock(MockBehavior.Strict); + var sendTweetsToSharedInboxTaskMock = new Mock( + MockBehavior.Strict + ); sendTweetsToSharedInboxTaskMock - .Setup(x => x.ExecuteAsync( - It.Is(y => y.Length == 1), - It.Is(y => y.Acct == userAcct), - It.Is(y => y == host1), - It.Is(y => y.Length == 1))) + .Setup( + x => + x.ExecuteAsync( + It.Is(y => y.Length == 1), + It.Is(y => y.Acct == userAcct), + It.Is(y => y == host1), + It.Is(y => y.Length == 1) + ) + ) .Returns(Task.CompletedTask); sendTweetsToSharedInboxTaskMock - .Setup(x => x.ExecuteAsync( - It.Is(y => y.Length == 1), - It.Is(y => y.Acct == userAcct), - It.Is(y => y == host2), - It.Is(y => y.Length == 1))) + .Setup( + x => + x.ExecuteAsync( + It.Is(y => y.Length == 1), + It.Is(y => y.Acct == userAcct), + It.Is(y => y == host2), + It.Is(y => y.Length == 1) + ) + ) .Throws(new Exception()); var followersDalMock = new Mock(MockBehavior.Strict); followersDalMock - .Setup(x => x.UpdateFollowerAsync(It.Is(y => y.Id == userId1 && y.PostingErrorCount == 0))) + .Setup( + x => + x.UpdateFollowerAsync( + It.Is(y => y.Id == userId1 && y.PostingErrorCount == 0) + ) + ) .Returns(Task.CompletedTask); followersDalMock - .Setup(x => x.UpdateFollowerAsync(It.Is(y => y.Id == userId2 && y.PostingErrorCount == 51))) + .Setup( + x => + x.UpdateFollowerAsync( + It.Is(y => y.Id == userId2 && y.PostingErrorCount == 51) + ) + ) .Returns(Task.CompletedTask); var loggerMock = new Mock>(); #endregion - var processor = new SendTweetsToFollowersProcessor(sendTweetsToInboxTaskMock.Object, sendTweetsToSharedInboxTaskMock.Object, followersDalMock.Object, loggerMock.Object); + var processor = new SendTweetsToFollowersProcessor( + sendTweetsToInboxTaskMock.Object, + sendTweetsToSharedInboxTaskMock.Object, + followersDalMock.Object, + loggerMock.Object + ); var result = await processor.ProcessAsync(userWithTweets, CancellationToken.None); #region Validations @@ -425,17 +470,8 @@ namespace BirdsiteLive.Pipeline.Tests.Processors var userWithTweets = new UserWithDataToSync() { - Tweets = new[] - { - new ExtractedTweet - { - Id = tweetId - } - }, - User = new SyncTwitterUser - { - Acct = userAcct - }, + Tweets = new[] { new ExtractedTweet { Id = tweetId } }, + User = new SyncTwitterUser { Acct = userAcct }, Followers = new[] { new Follower @@ -459,21 +495,32 @@ namespace BirdsiteLive.Pipeline.Tests.Processors foreach (var userId in new[] { userId1, userId2 }) { sendTweetsToInboxTaskMock - .Setup(x => x.ExecuteAsync( - It.Is(y => y.Length == 1), - It.Is(y => y.Id == userId), - It.Is(y => y.Acct == userAcct))) + .Setup( + x => + x.ExecuteAsync( + It.Is(y => y.Length == 1), + It.Is(y => y.Id == userId), + It.Is(y => y.Acct == userAcct) + ) + ) .Returns(Task.CompletedTask); } - var sendTweetsToSharedInboxTaskMock = new Mock(MockBehavior.Strict); + var sendTweetsToSharedInboxTaskMock = new Mock( + MockBehavior.Strict + ); var followersDalMock = new Mock(MockBehavior.Strict); var loggerMock = new Mock>(); #endregion - var processor = new SendTweetsToFollowersProcessor(sendTweetsToInboxTaskMock.Object, sendTweetsToSharedInboxTaskMock.Object, followersDalMock.Object, loggerMock.Object); + var processor = new SendTweetsToFollowersProcessor( + sendTweetsToInboxTaskMock.Object, + sendTweetsToSharedInboxTaskMock.Object, + followersDalMock.Object, + loggerMock.Object + ); var result = await processor.ProcessAsync(userWithTweets, CancellationToken.None); #region Validations @@ -497,17 +544,8 @@ namespace BirdsiteLive.Pipeline.Tests.Processors var userWithTweets = new UserWithDataToSync() { - Tweets = new[] - { - new ExtractedTweet - { - Id = tweetId - } - }, - User = new SyncTwitterUser - { - Acct = userAcct - }, + Tweets = new[] { new ExtractedTweet { Id = tweetId } }, + User = new SyncTwitterUser { Acct = userAcct }, Followers = new[] { new Follower @@ -531,21 +569,32 @@ namespace BirdsiteLive.Pipeline.Tests.Processors foreach (var userId in new[] { userId1, userId2 }) { sendTweetsToInboxTaskMock - .Setup(x => x.ExecuteAsync( - It.Is(y => y.Length == 1), - It.Is(y => y.Id == userId), - It.Is(y => y.Acct == userAcct))) + .Setup( + x => + x.ExecuteAsync( + It.Is(y => y.Length == 1), + It.Is(y => y.Id == userId), + It.Is(y => y.Acct == userAcct) + ) + ) .Returns(Task.CompletedTask); } - var sendTweetsToSharedInboxTaskMock = new Mock(MockBehavior.Strict); + var sendTweetsToSharedInboxTaskMock = new Mock( + MockBehavior.Strict + ); var followersDalMock = new Mock(MockBehavior.Strict); var loggerMock = new Mock>(); #endregion - var processor = new SendTweetsToFollowersProcessor(sendTweetsToInboxTaskMock.Object, sendTweetsToSharedInboxTaskMock.Object, followersDalMock.Object, loggerMock.Object); + var processor = new SendTweetsToFollowersProcessor( + sendTweetsToInboxTaskMock.Object, + sendTweetsToSharedInboxTaskMock.Object, + followersDalMock.Object, + loggerMock.Object + ); var result = await processor.ProcessAsync(userWithTweets, CancellationToken.None); #region Validations @@ -569,17 +618,8 @@ namespace BirdsiteLive.Pipeline.Tests.Processors var userWithTweets = new UserWithDataToSync() { - Tweets = new[] - { - new ExtractedTweet - { - Id = tweetId - } - }, - User = new SyncTwitterUser - { - Acct = userAcct - }, + Tweets = new[] { new ExtractedTweet { Id = tweetId } }, + User = new SyncTwitterUser { Acct = userAcct }, Followers = new[] { new Follower @@ -601,31 +641,51 @@ namespace BirdsiteLive.Pipeline.Tests.Processors #region Mocks var sendTweetsToInboxTaskMock = new Mock(MockBehavior.Strict); sendTweetsToInboxTaskMock - .Setup(x => x.ExecuteAsync( - It.Is(y => y.Length == 1), - It.Is(y => y.Id == userId1), - It.Is(y => y.Acct == userAcct))) + .Setup( + x => + x.ExecuteAsync( + It.Is(y => y.Length == 1), + It.Is(y => y.Id == userId1), + It.Is(y => y.Acct == userAcct) + ) + ) .Returns(Task.CompletedTask); sendTweetsToInboxTaskMock - .Setup(x => x.ExecuteAsync( - It.Is(y => y.Length == 1), - It.Is(y => y.Id == userId2), - It.Is(y => y.Acct == userAcct))) + .Setup( + x => + x.ExecuteAsync( + It.Is(y => y.Length == 1), + It.Is(y => y.Id == userId2), + It.Is(y => y.Acct == userAcct) + ) + ) .Throws(new Exception()); - var sendTweetsToSharedInboxTaskMock = new Mock(MockBehavior.Strict); + var sendTweetsToSharedInboxTaskMock = new Mock( + MockBehavior.Strict + ); var followersDalMock = new Mock(MockBehavior.Strict); - + followersDalMock - .Setup(x => x.UpdateFollowerAsync(It.Is(y => y.Id == userId2 && y.PostingErrorCount == 1))) + .Setup( + x => + x.UpdateFollowerAsync( + It.Is(y => y.Id == userId2 && y.PostingErrorCount == 1) + ) + ) .Returns(Task.CompletedTask); var loggerMock = new Mock>(); #endregion - var processor = new SendTweetsToFollowersProcessor(sendTweetsToInboxTaskMock.Object, sendTweetsToSharedInboxTaskMock.Object, followersDalMock.Object, loggerMock.Object); + var processor = new SendTweetsToFollowersProcessor( + sendTweetsToInboxTaskMock.Object, + sendTweetsToSharedInboxTaskMock.Object, + followersDalMock.Object, + loggerMock.Object + ); var result = await processor.ProcessAsync(userWithTweets, CancellationToken.None); #region Validations @@ -649,17 +709,8 @@ namespace BirdsiteLive.Pipeline.Tests.Processors var userWithTweets = new UserWithDataToSync() { - Tweets = new[] - { - new ExtractedTweet - { - Id = tweetId - } - }, - User = new SyncTwitterUser - { - Acct = userAcct - }, + Tweets = new[] { new ExtractedTweet { Id = tweetId } }, + User = new SyncTwitterUser { Acct = userAcct }, Followers = new[] { new Follower @@ -682,31 +733,51 @@ namespace BirdsiteLive.Pipeline.Tests.Processors #region Mocks var sendTweetsToInboxTaskMock = new Mock(MockBehavior.Strict); sendTweetsToInboxTaskMock - .Setup(x => x.ExecuteAsync( - It.Is(y => y.Length == 1), - It.Is(y => y.Id == userId1), - It.Is(y => y.Acct == userAcct))) + .Setup( + x => + x.ExecuteAsync( + It.Is(y => y.Length == 1), + It.Is(y => y.Id == userId1), + It.Is(y => y.Acct == userAcct) + ) + ) .Returns(Task.CompletedTask); sendTweetsToInboxTaskMock - .Setup(x => x.ExecuteAsync( - It.Is(y => y.Length == 1), - It.Is(y => y.Id == userId2), - It.Is(y => y.Acct == userAcct))) + .Setup( + x => + x.ExecuteAsync( + It.Is(y => y.Length == 1), + It.Is(y => y.Id == userId2), + It.Is(y => y.Acct == userAcct) + ) + ) .Returns(Task.CompletedTask); - var sendTweetsToSharedInboxTaskMock = new Mock(MockBehavior.Strict); + var sendTweetsToSharedInboxTaskMock = new Mock( + MockBehavior.Strict + ); var followersDalMock = new Mock(MockBehavior.Strict); followersDalMock - .Setup(x => x.UpdateFollowerAsync(It.Is(y => y.Id == userId2 && y.PostingErrorCount == 0))) + .Setup( + x => + x.UpdateFollowerAsync( + It.Is(y => y.Id == userId2 && y.PostingErrorCount == 0) + ) + ) .Returns(Task.CompletedTask); var loggerMock = new Mock>(); #endregion - var processor = new SendTweetsToFollowersProcessor(sendTweetsToInboxTaskMock.Object, sendTweetsToSharedInboxTaskMock.Object, followersDalMock.Object, loggerMock.Object); + var processor = new SendTweetsToFollowersProcessor( + sendTweetsToInboxTaskMock.Object, + sendTweetsToSharedInboxTaskMock.Object, + followersDalMock.Object, + loggerMock.Object + ); var result = await processor.ProcessAsync(userWithTweets, CancellationToken.None); #region Validations @@ -730,17 +801,8 @@ namespace BirdsiteLive.Pipeline.Tests.Processors var userWithTweets = new UserWithDataToSync() { - Tweets = new[] - { - new ExtractedTweet - { - Id = tweetId - } - }, - User = new SyncTwitterUser - { - Acct = userAcct - }, + Tweets = new[] { new ExtractedTweet { Id = tweetId } }, + User = new SyncTwitterUser { Acct = userAcct }, Followers = new[] { new Follower @@ -764,35 +826,60 @@ namespace BirdsiteLive.Pipeline.Tests.Processors #region Mocks var sendTweetsToInboxTaskMock = new Mock(MockBehavior.Strict); sendTweetsToInboxTaskMock - .Setup(x => x.ExecuteAsync( - It.Is(y => y.Length == 1), - It.Is(y => y.Id == userId1), - It.Is(y => y.Acct == userAcct))) + .Setup( + x => + x.ExecuteAsync( + It.Is(y => y.Length == 1), + It.Is(y => y.Id == userId1), + It.Is(y => y.Acct == userAcct) + ) + ) .Returns(Task.CompletedTask); sendTweetsToInboxTaskMock - .Setup(x => x.ExecuteAsync( - It.Is(y => y.Length == 1), - It.Is(y => y.Id == userId2), - It.Is(y => y.Acct == userAcct))) + .Setup( + x => + x.ExecuteAsync( + It.Is(y => y.Length == 1), + It.Is(y => y.Id == userId2), + It.Is(y => y.Acct == userAcct) + ) + ) .Throws(new Exception()); - var sendTweetsToSharedInboxTaskMock = new Mock(MockBehavior.Strict); + var sendTweetsToSharedInboxTaskMock = new Mock( + MockBehavior.Strict + ); var followersDalMock = new Mock(MockBehavior.Strict); followersDalMock - .Setup(x => x.UpdateFollowerAsync(It.Is(y => y.Id == userId1 && y.PostingErrorCount == 0))) + .Setup( + x => + x.UpdateFollowerAsync( + It.Is(y => y.Id == userId1 && y.PostingErrorCount == 0) + ) + ) .Returns(Task.CompletedTask); followersDalMock - .Setup(x => x.UpdateFollowerAsync(It.Is(y => y.Id == userId2 && y.PostingErrorCount == 51))) + .Setup( + x => + x.UpdateFollowerAsync( + It.Is(y => y.Id == userId2 && y.PostingErrorCount == 51) + ) + ) .Returns(Task.CompletedTask); var loggerMock = new Mock>(); #endregion - var processor = new SendTweetsToFollowersProcessor(sendTweetsToInboxTaskMock.Object, sendTweetsToSharedInboxTaskMock.Object, followersDalMock.Object, loggerMock.Object); + var processor = new SendTweetsToFollowersProcessor( + sendTweetsToInboxTaskMock.Object, + sendTweetsToSharedInboxTaskMock.Object, + followersDalMock.Object, + loggerMock.Object + ); var result = await processor.ProcessAsync(userWithTweets, CancellationToken.None); #region Validations @@ -802,4 +889,4 @@ namespace BirdsiteLive.Pipeline.Tests.Processors #endregion } } -} \ No newline at end of file +} diff --git a/src/Tests/BirdsiteLive.Pipeline.Tests/Processors/SubTasks/SendTweetsToInboxTaskTests.cs b/src/Tests/BirdsiteLive.Pipeline.Tests/Processors/SubTasks/SendTweetsToInboxTaskTests.cs index 367a642..4b8bd2a 100644 --- a/src/Tests/BirdsiteLive.Pipeline.Tests/Processors/SubTasks/SendTweetsToInboxTaskTests.cs +++ b/src/Tests/BirdsiteLive.Pipeline.Tests/Processors/SubTasks/SendTweetsToInboxTaskTests.cs @@ -1,8 +1,9 @@ -using System; +using System; using System.Collections.Generic; using System.Net; using System.Net.Http; using System.Threading.Tasks; + using BirdsiteLive.ActivityPub.Models; using BirdsiteLive.Common.Settings; using BirdsiteLive.DAL.Contracts; @@ -10,8 +11,10 @@ using BirdsiteLive.DAL.Models; using BirdsiteLive.Domain; using BirdsiteLive.Pipeline.Processors.SubTasks; using BirdsiteLive.Twitter.Models; + using Microsoft.Extensions.Logging; using Microsoft.VisualStudio.TestTools.UnitTesting; + using Moq; namespace BirdsiteLive.Pipeline.Tests.Processors.SubTasks @@ -24,27 +27,14 @@ namespace BirdsiteLive.Pipeline.Tests.Processors.SubTasks { #region Stubs var tweetId = 10; - var tweets = new List - { - new ExtractedTweet - { - Id = tweetId, - } - }; + var tweets = new List { new ExtractedTweet { Id = tweetId, } }; var noteId = "noteId"; - var note = new Note() - { - id = noteId - }; + var note = new Note() { id = noteId }; var twitterHandle = "Test"; var twitterUserId = 7; - var twitterUser = new SyncTwitterUser - { - Id = twitterUserId, - Acct = twitterHandle - }; + var twitterUser = new SyncTwitterUser { Id = twitterUserId, Acct = twitterHandle }; var host = "domain.ext"; var inbox = "/user/inbox"; @@ -56,40 +46,59 @@ namespace BirdsiteLive.Pipeline.Tests.Processors.SubTasks FollowingsSyncStatus = new Dictionary { { twitterUserId, 9 } } }; - var settings = new InstanceSettings - { - PublishReplies = false - }; + var settings = new InstanceSettings { PublishReplies = false }; #endregion #region Mocks var activityPubService = new Mock(MockBehavior.Strict); activityPubService - .Setup(x => x.PostNewNoteActivity( - It.Is(y => y.id == noteId), - It.Is(y => y == twitterHandle), - It.Is(y => y == tweetId.ToString()), - It.Is(y => y == host), - It.Is(y => y == inbox))) + .Setup( + x => + x.PostNewNoteActivity( + It.Is(y => y.id == noteId), + It.Is(y => y == twitterHandle), + It.Is(y => y == tweetId.ToString()), + It.Is(y => y == host), + It.Is(y => y == inbox) + ) + ) .Returns(Task.CompletedTask); var statusServiceMock = new Mock(MockBehavior.Strict); statusServiceMock - .Setup(x => x.GetStatus( - It.Is(y => y == twitterHandle), - It.Is(y => y.Id == tweetId))) + .Setup( + x => + x.GetStatus( + It.Is(y => y == twitterHandle), + It.Is(y => y.Id == tweetId) + ) + ) .Returns(note); var followersDalMock = new Mock(MockBehavior.Strict); followersDalMock - .Setup(x => x.UpdateFollowerAsync( - It.Is(y => y.Id == follower.Id && y.FollowingsSyncStatus[twitterUserId] == tweetId))) + .Setup( + x => + x.UpdateFollowerAsync( + It.Is( + y => + y.Id == follower.Id + && y.FollowingsSyncStatus[twitterUserId] == tweetId + ) + ) + ) .Returns(Task.CompletedTask); var loggerMock = new Mock>(); #endregion - var task = new SendTweetsToInboxTask(activityPubService.Object, statusServiceMock.Object, followersDalMock.Object, settings, loggerMock.Object); + var task = new SendTweetsToInboxTask( + activityPubService.Object, + statusServiceMock.Object, + followersDalMock.Object, + settings, + loggerMock.Object + ); await task.ExecuteAsync(tweets.ToArray(), follower, twitterUser); #region Validations @@ -115,18 +124,11 @@ namespace BirdsiteLive.Pipeline.Tests.Processors.SubTasks }; var noteId = "noteId"; - var note = new Note() - { - id = noteId - }; + var note = new Note() { id = noteId }; var twitterHandle = "Test"; var twitterUserId = 7; - var twitterUser = new SyncTwitterUser - { - Id = twitterUserId, - Acct = twitterHandle - }; + var twitterUser = new SyncTwitterUser { Id = twitterUserId, Acct = twitterHandle }; var host = "domain.ext"; var inbox = "/user/inbox"; @@ -138,10 +140,7 @@ namespace BirdsiteLive.Pipeline.Tests.Processors.SubTasks FollowingsSyncStatus = new Dictionary { { twitterUserId, 9 } } }; - var settings = new InstanceSettings - { - PublishReplies = false - }; + var settings = new InstanceSettings { PublishReplies = false }; #endregion #region Mocks @@ -150,14 +149,28 @@ namespace BirdsiteLive.Pipeline.Tests.Processors.SubTasks var followersDalMock = new Mock(MockBehavior.Strict); followersDalMock - .Setup(x => x.UpdateFollowerAsync( - It.Is(y => y.Id == follower.Id && y.FollowingsSyncStatus[twitterUserId] == tweetId))) + .Setup( + x => + x.UpdateFollowerAsync( + It.Is( + y => + y.Id == follower.Id + && y.FollowingsSyncStatus[twitterUserId] == tweetId + ) + ) + ) .Returns(Task.CompletedTask); var loggerMock = new Mock>(); #endregion - var task = new SendTweetsToInboxTask(activityPubService.Object, statusServiceMock.Object, followersDalMock.Object, settings, loggerMock.Object); + var task = new SendTweetsToInboxTask( + activityPubService.Object, + statusServiceMock.Object, + followersDalMock.Object, + settings, + loggerMock.Object + ); await task.ExecuteAsync(tweets.ToArray(), follower, twitterUser); #region Validations @@ -183,18 +196,11 @@ namespace BirdsiteLive.Pipeline.Tests.Processors.SubTasks }; var noteId = "noteId"; - var note = new Note() - { - id = noteId - }; + var note = new Note() { id = noteId }; var twitterHandle = "Test"; var twitterUserId = 7; - var twitterUser = new SyncTwitterUser - { - Id = twitterUserId, - Acct = twitterHandle - }; + var twitterUser = new SyncTwitterUser { Id = twitterUserId, Acct = twitterHandle }; var host = "domain.ext"; var inbox = "/user/inbox"; @@ -206,40 +212,59 @@ namespace BirdsiteLive.Pipeline.Tests.Processors.SubTasks FollowingsSyncStatus = new Dictionary { { twitterUserId, 9 } } }; - var settings = new InstanceSettings - { - PublishReplies = false - }; + var settings = new InstanceSettings { PublishReplies = false }; #endregion #region Mocks var activityPubService = new Mock(MockBehavior.Strict); activityPubService - .Setup(x => x.PostNewNoteActivity( - It.Is(y => y.id == noteId), - It.Is(y => y == twitterHandle), - It.Is(y => y == tweetId.ToString()), - It.Is(y => y == host), - It.Is(y => y == inbox))) + .Setup( + x => + x.PostNewNoteActivity( + It.Is(y => y.id == noteId), + It.Is(y => y == twitterHandle), + It.Is(y => y == tweetId.ToString()), + It.Is(y => y == host), + It.Is(y => y == inbox) + ) + ) .Returns(Task.CompletedTask); var statusServiceMock = new Mock(MockBehavior.Strict); statusServiceMock - .Setup(x => x.GetStatus( - It.Is(y => y == twitterHandle), - It.Is(y => y.Id == tweetId))) + .Setup( + x => + x.GetStatus( + It.Is(y => y == twitterHandle), + It.Is(y => y.Id == tweetId) + ) + ) .Returns(note); var followersDalMock = new Mock(MockBehavior.Strict); followersDalMock - .Setup(x => x.UpdateFollowerAsync( - It.Is(y => y.Id == follower.Id && y.FollowingsSyncStatus[twitterUserId] == tweetId))) + .Setup( + x => + x.UpdateFollowerAsync( + It.Is( + y => + y.Id == follower.Id + && y.FollowingsSyncStatus[twitterUserId] == tweetId + ) + ) + ) .Returns(Task.CompletedTask); var loggerMock = new Mock>(); #endregion - var task = new SendTweetsToInboxTask(activityPubService.Object, statusServiceMock.Object, followersDalMock.Object, settings, loggerMock.Object); + var task = new SendTweetsToInboxTask( + activityPubService.Object, + statusServiceMock.Object, + followersDalMock.Object, + settings, + loggerMock.Object + ); await task.ExecuteAsync(tweets.ToArray(), follower, twitterUser); #region Validations @@ -265,18 +290,11 @@ namespace BirdsiteLive.Pipeline.Tests.Processors.SubTasks }; var noteId = "noteId"; - var note = new Note() - { - id = noteId - }; + var note = new Note() { id = noteId }; var twitterHandle = "Test"; var twitterUserId = 7; - var twitterUser = new SyncTwitterUser - { - Id = twitterUserId, - Acct = twitterHandle - }; + var twitterUser = new SyncTwitterUser { Id = twitterUserId, Acct = twitterHandle }; var host = "domain.ext"; var inbox = "/user/inbox"; @@ -288,40 +306,59 @@ namespace BirdsiteLive.Pipeline.Tests.Processors.SubTasks FollowingsSyncStatus = new Dictionary { { twitterUserId, 9 } } }; - var settings = new InstanceSettings - { - PublishReplies = true - }; + var settings = new InstanceSettings { PublishReplies = true }; #endregion #region Mocks var activityPubService = new Mock(MockBehavior.Strict); activityPubService - .Setup(x => x.PostNewNoteActivity( - It.Is(y => y.id == noteId), - It.Is(y => y == twitterHandle), - It.Is(y => y == tweetId.ToString()), - It.Is(y => y == host), - It.Is(y => y == inbox))) + .Setup( + x => + x.PostNewNoteActivity( + It.Is(y => y.id == noteId), + It.Is(y => y == twitterHandle), + It.Is(y => y == tweetId.ToString()), + It.Is(y => y == host), + It.Is(y => y == inbox) + ) + ) .Returns(Task.CompletedTask); var statusServiceMock = new Mock(MockBehavior.Strict); statusServiceMock - .Setup(x => x.GetStatus( - It.Is(y => y == twitterHandle), - It.Is(y => y.Id == tweetId))) + .Setup( + x => + x.GetStatus( + It.Is(y => y == twitterHandle), + It.Is(y => y.Id == tweetId) + ) + ) .Returns(note); var followersDalMock = new Mock(MockBehavior.Strict); followersDalMock - .Setup(x => x.UpdateFollowerAsync( - It.Is(y => y.Id == follower.Id && y.FollowingsSyncStatus[twitterUserId] == tweetId))) + .Setup( + x => + x.UpdateFollowerAsync( + It.Is( + y => + y.Id == follower.Id + && y.FollowingsSyncStatus[twitterUserId] == tweetId + ) + ) + ) .Returns(Task.CompletedTask); var loggerMock = new Mock>(); #endregion - var task = new SendTweetsToInboxTask(activityPubService.Object, statusServiceMock.Object, followersDalMock.Object, settings, loggerMock.Object); + var task = new SendTweetsToInboxTask( + activityPubService.Object, + statusServiceMock.Object, + followersDalMock.Object, + settings, + loggerMock.Object + ); await task.ExecuteAsync(tweets.ToArray(), follower, twitterUser); #region Validations @@ -341,19 +378,12 @@ namespace BirdsiteLive.Pipeline.Tests.Processors.SubTasks var tweets = new List(); foreach (var tweetId in new[] { tweetId1, tweetId2, tweetId3 }) { - tweets.Add(new ExtractedTweet - { - Id = tweetId - }); + tweets.Add(new ExtractedTweet { Id = tweetId }); } var twitterHandle = "Test"; var twitterUserId = 7; - var twitterUser = new SyncTwitterUser - { - Id = twitterUserId, - Acct = twitterHandle - }; + var twitterUser = new SyncTwitterUser { Id = twitterUserId, Acct = twitterHandle }; var host = "domain.ext"; var inbox = "/user/inbox"; @@ -365,10 +395,7 @@ namespace BirdsiteLive.Pipeline.Tests.Processors.SubTasks FollowingsSyncStatus = new Dictionary { { twitterUserId, 10 } } }; - var settings = new InstanceSettings - { - PublishReplies = false - }; + var settings = new InstanceSettings { PublishReplies = false }; #endregion #region Mocks @@ -376,12 +403,16 @@ namespace BirdsiteLive.Pipeline.Tests.Processors.SubTasks foreach (var tweetId in new[] { tweetId2, tweetId3 }) { activityPubService - .Setup(x => x.PostNewNoteActivity( - It.Is(y => y.id == tweetId.ToString()), - It.Is(y => y == twitterHandle), - It.Is(y => y == tweetId.ToString()), - It.Is(y => y == host), - It.Is(y => y == inbox))) + .Setup( + x => + x.PostNewNoteActivity( + It.Is(y => y.id == tweetId.ToString()), + It.Is(y => y == twitterHandle), + It.Is(y => y == tweetId.ToString()), + It.Is(y => y == host), + It.Is(y => y == inbox) + ) + ) .Returns(Task.CompletedTask); } @@ -389,22 +420,40 @@ namespace BirdsiteLive.Pipeline.Tests.Processors.SubTasks foreach (var tweetId in new[] { tweetId2, tweetId3 }) { statusServiceMock - .Setup(x => x.GetStatus( - It.Is(y => y == twitterHandle), - It.Is(y => y.Id == tweetId))) + .Setup( + x => + x.GetStatus( + It.Is(y => y == twitterHandle), + It.Is(y => y.Id == tweetId) + ) + ) .Returns(new Note { id = tweetId.ToString() }); } var followersDalMock = new Mock(MockBehavior.Strict); followersDalMock - .Setup(x => x.UpdateFollowerAsync( - It.Is(y => y.Id == follower.Id && y.FollowingsSyncStatus[twitterUserId] == tweetId3))) + .Setup( + x => + x.UpdateFollowerAsync( + It.Is( + y => + y.Id == follower.Id + && y.FollowingsSyncStatus[twitterUserId] == tweetId3 + ) + ) + ) .Returns(Task.CompletedTask); var loggerMock = new Mock>(); #endregion - var task = new SendTweetsToInboxTask(activityPubService.Object, statusServiceMock.Object, followersDalMock.Object, settings, loggerMock.Object); + var task = new SendTweetsToInboxTask( + activityPubService.Object, + statusServiceMock.Object, + followersDalMock.Object, + settings, + loggerMock.Object + ); await task.ExecuteAsync(tweets.ToArray(), follower, twitterUser); #region Validations @@ -425,19 +474,12 @@ namespace BirdsiteLive.Pipeline.Tests.Processors.SubTasks var tweets = new List(); foreach (var tweetId in new[] { tweetId1, tweetId2, tweetId3 }) { - tweets.Add(new ExtractedTweet - { - Id = tweetId - }); + tweets.Add(new ExtractedTweet { Id = tweetId }); } var twitterHandle = "Test"; var twitterUserId = 7; - var twitterUser = new SyncTwitterUser - { - Id = twitterUserId, - Acct = twitterHandle - }; + var twitterUser = new SyncTwitterUser { Id = twitterUserId, Acct = twitterHandle }; var host = "domain.ext"; var inbox = "/user/inbox"; @@ -449,53 +491,76 @@ namespace BirdsiteLive.Pipeline.Tests.Processors.SubTasks FollowingsSyncStatus = new Dictionary { { twitterUserId, 10 } } }; - var settings = new InstanceSettings - { - PublishReplies = false - }; + var settings = new InstanceSettings { PublishReplies = false }; #endregion #region Mocks var activityPubService = new Mock(MockBehavior.Strict); activityPubService - .Setup(x => x.PostNewNoteActivity( - It.Is(y => y.id == tweetId2.ToString()), - It.Is(y => y == twitterHandle), - It.Is(y => y == tweetId2.ToString()), - It.Is(y => y == host), - It.Is(y => y == inbox))) + .Setup( + x => + x.PostNewNoteActivity( + It.Is(y => y.id == tweetId2.ToString()), + It.Is(y => y == twitterHandle), + It.Is(y => y == tweetId2.ToString()), + It.Is(y => y == host), + It.Is(y => y == inbox) + ) + ) .Returns(Task.CompletedTask); activityPubService - .Setup(x => x.PostNewNoteActivity( - It.Is(y => y.id == tweetId3.ToString()), - It.Is(y => y == twitterHandle), - It.Is(y => y == tweetId3.ToString()), - It.Is(y => y == host), - It.Is(y => y == inbox))) + .Setup( + x => + x.PostNewNoteActivity( + It.Is(y => y.id == tweetId3.ToString()), + It.Is(y => y == twitterHandle), + It.Is(y => y == tweetId3.ToString()), + It.Is(y => y == host), + It.Is(y => y == inbox) + ) + ) .Throws(new HttpRequestException()); var statusServiceMock = new Mock(MockBehavior.Strict); foreach (var tweetId in new[] { tweetId2, tweetId3 }) { statusServiceMock - .Setup(x => x.GetStatus( - It.Is(y => y == twitterHandle), - It.Is(y => y.Id == tweetId))) + .Setup( + x => + x.GetStatus( + It.Is(y => y == twitterHandle), + It.Is(y => y.Id == tweetId) + ) + ) .Returns(new Note { id = tweetId.ToString() }); } var followersDalMock = new Mock(MockBehavior.Strict); followersDalMock - .Setup(x => x.UpdateFollowerAsync( - It.Is(y => y.Id == follower.Id && y.FollowingsSyncStatus[twitterUserId] == tweetId2))) + .Setup( + x => + x.UpdateFollowerAsync( + It.Is( + y => + y.Id == follower.Id + && y.FollowingsSyncStatus[twitterUserId] == tweetId2 + ) + ) + ) .Returns(Task.CompletedTask); var loggerMock = new Mock>(); #endregion - var task = new SendTweetsToInboxTask(activityPubService.Object, statusServiceMock.Object, followersDalMock.Object, settings, loggerMock.Object); + var task = new SendTweetsToInboxTask( + activityPubService.Object, + statusServiceMock.Object, + followersDalMock.Object, + settings, + loggerMock.Object + ); try { @@ -516,27 +581,14 @@ namespace BirdsiteLive.Pipeline.Tests.Processors.SubTasks { #region Stubs var tweetId = 10; - var tweets = new List - { - new ExtractedTweet - { - Id = tweetId, - } - }; + var tweets = new List { new ExtractedTweet { Id = tweetId, } }; var noteId = "noteId"; - var note = new Note() - { - id = noteId - }; + var note = new Note() { id = noteId }; var twitterHandle = "Test"; var twitterUserId = 7; - var twitterUser = new SyncTwitterUser - { - Id = twitterUserId, - Acct = twitterHandle - }; + var twitterUser = new SyncTwitterUser { Id = twitterUserId, Acct = twitterHandle }; var host = "domain.ext"; var inbox = "/user/inbox"; @@ -548,10 +600,7 @@ namespace BirdsiteLive.Pipeline.Tests.Processors.SubTasks FollowingsSyncStatus = new Dictionary { { twitterUserId, 9 } } }; - var settings = new InstanceSettings - { - PublishReplies = false - }; + var settings = new InstanceSettings { PublishReplies = false }; #endregion #region Mocks @@ -559,21 +608,39 @@ namespace BirdsiteLive.Pipeline.Tests.Processors.SubTasks var statusServiceMock = new Mock(MockBehavior.Strict); statusServiceMock - .Setup(x => x.GetStatus( - It.Is(y => y == twitterHandle), - It.Is(y => y.Id == tweetId))) + .Setup( + x => + x.GetStatus( + It.Is(y => y == twitterHandle), + It.Is(y => y.Id == tweetId) + ) + ) .Throws(new ArgumentException("Invalid pattern blabla at offset 9")); var followersDalMock = new Mock(MockBehavior.Strict); followersDalMock - .Setup(x => x.UpdateFollowerAsync( - It.Is(y => y.Id == follower.Id && y.FollowingsSyncStatus[twitterUserId] == tweetId))) + .Setup( + x => + x.UpdateFollowerAsync( + It.Is( + y => + y.Id == follower.Id + && y.FollowingsSyncStatus[twitterUserId] == tweetId + ) + ) + ) .Returns(Task.CompletedTask); var loggerMock = new Mock>(); #endregion - var task = new SendTweetsToInboxTask(activityPubService.Object, statusServiceMock.Object, followersDalMock.Object, settings, loggerMock.Object); + var task = new SendTweetsToInboxTask( + activityPubService.Object, + statusServiceMock.Object, + followersDalMock.Object, + settings, + loggerMock.Object + ); await task.ExecuteAsync(tweets.ToArray(), follower, twitterUser); #region Validations @@ -589,21 +656,11 @@ namespace BirdsiteLive.Pipeline.Tests.Processors.SubTasks { #region Stubs var tweetId = 10; - var tweets = new List - { - new ExtractedTweet - { - Id = tweetId, - } - }; + var tweets = new List { new ExtractedTweet { Id = tweetId, } }; var twitterHandle = "Test"; var twitterUserId = 7; - var twitterUser = new SyncTwitterUser - { - Id = twitterUserId, - Acct = twitterHandle - }; + var twitterUser = new SyncTwitterUser { Id = twitterUserId, Acct = twitterHandle }; var host = "domain.ext"; var inbox = "/user/inbox"; @@ -615,10 +672,7 @@ namespace BirdsiteLive.Pipeline.Tests.Processors.SubTasks FollowingsSyncStatus = new Dictionary { { twitterUserId, 9 } } }; - var settings = new InstanceSettings - { - PublishReplies = false - }; + var settings = new InstanceSettings { PublishReplies = false }; #endregion #region Mocks @@ -626,9 +680,13 @@ namespace BirdsiteLive.Pipeline.Tests.Processors.SubTasks var statusServiceMock = new Mock(MockBehavior.Strict); statusServiceMock - .Setup(x => x.GetStatus( - It.Is(y => y == twitterHandle), - It.Is(y => y.Id == tweetId))) + .Setup( + x => + x.GetStatus( + It.Is(y => y == twitterHandle), + It.Is(y => y.Id == tweetId) + ) + ) .Throws(new ArgumentException()); var followersDalMock = new Mock(MockBehavior.Strict); @@ -636,12 +694,17 @@ namespace BirdsiteLive.Pipeline.Tests.Processors.SubTasks var loggerMock = new Mock>(); #endregion - var task = new SendTweetsToInboxTask(activityPubService.Object, statusServiceMock.Object, followersDalMock.Object, settings, loggerMock.Object); + var task = new SendTweetsToInboxTask( + activityPubService.Object, + statusServiceMock.Object, + followersDalMock.Object, + settings, + loggerMock.Object + ); try { await task.ExecuteAsync(tweets.ToArray(), follower, twitterUser); - } finally { @@ -653,4 +716,4 @@ namespace BirdsiteLive.Pipeline.Tests.Processors.SubTasks } } } -} \ No newline at end of file +} diff --git a/src/Tests/BirdsiteLive.Pipeline.Tests/Processors/SubTasks/SendTweetsToSharedInboxTests.cs b/src/Tests/BirdsiteLive.Pipeline.Tests/Processors/SubTasks/SendTweetsToSharedInboxTests.cs index 7ab06a2..a84acec 100644 --- a/src/Tests/BirdsiteLive.Pipeline.Tests/Processors/SubTasks/SendTweetsToSharedInboxTests.cs +++ b/src/Tests/BirdsiteLive.Pipeline.Tests/Processors/SubTasks/SendTweetsToSharedInboxTests.cs @@ -1,9 +1,10 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Http; using System.Threading.Tasks; + using BirdsiteLive.ActivityPub.Models; using BirdsiteLive.Common.Settings; using BirdsiteLive.DAL.Contracts; @@ -11,8 +12,10 @@ using BirdsiteLive.DAL.Models; using BirdsiteLive.Domain; using BirdsiteLive.Pipeline.Processors.SubTasks; using BirdsiteLive.Twitter.Models; + using Microsoft.Extensions.Logging; using Microsoft.VisualStudio.TestTools.UnitTesting; + using Moq; namespace BirdsiteLive.Pipeline.Tests.Processors.SubTasks @@ -25,27 +28,14 @@ namespace BirdsiteLive.Pipeline.Tests.Processors.SubTasks { #region Stubs var tweetId = 10; - var tweets = new List - { - new ExtractedTweet - { - Id = tweetId, - } - }; + var tweets = new List { new ExtractedTweet { Id = tweetId, } }; var noteId = "noteId"; - var note = new Note() - { - id = noteId - }; + var note = new Note() { id = noteId }; var twitterHandle = "Test"; var twitterUserId = 7; - var twitterUser = new SyncTwitterUser - { - Id = twitterUserId, - Acct = twitterHandle - }; + var twitterUser = new SyncTwitterUser { Id = twitterUserId, Acct = twitterHandle }; var host = "domain.ext"; var inbox = "/inbox"; @@ -74,28 +64,33 @@ namespace BirdsiteLive.Pipeline.Tests.Processors.SubTasks } }; - var settings = new InstanceSettings - { - PublishReplies = false - }; + var settings = new InstanceSettings { PublishReplies = false }; #endregion #region Mocks var activityPubService = new Mock(MockBehavior.Strict); activityPubService - .Setup(x => x.PostNewNoteActivity( - It.Is(y => y.id == noteId), - It.Is(y => y == twitterHandle), - It.Is(y => y == tweetId.ToString()), - It.Is(y => y == host), - It.Is(y => y == inbox))) + .Setup( + x => + x.PostNewNoteActivity( + It.Is(y => y.id == noteId), + It.Is(y => y == twitterHandle), + It.Is(y => y == tweetId.ToString()), + It.Is(y => y == host), + It.Is(y => y == inbox) + ) + ) .Returns(Task.CompletedTask); var statusServiceMock = new Mock(MockBehavior.Strict); statusServiceMock - .Setup(x => x.GetStatus( - It.Is(y => y == twitterHandle), - It.Is(y => y.Id == tweetId))) + .Setup( + x => + x.GetStatus( + It.Is(y => y == twitterHandle), + It.Is(y => y.Id == tweetId) + ) + ) .Returns(note); var followersDalMock = new Mock(MockBehavior.Strict); @@ -103,15 +98,29 @@ namespace BirdsiteLive.Pipeline.Tests.Processors.SubTasks foreach (var follower in followers) { followersDalMock - .Setup(x => x.UpdateFollowerAsync( - It.Is(y => y.Id == follower.Id && y.FollowingsSyncStatus[twitterUserId] == tweetId))) + .Setup( + x => + x.UpdateFollowerAsync( + It.Is( + y => + y.Id == follower.Id + && y.FollowingsSyncStatus[twitterUserId] == tweetId + ) + ) + ) .Returns(Task.CompletedTask); } var loggerMock = new Mock>(); #endregion - var task = new SendTweetsToSharedInboxTask(activityPubService.Object, statusServiceMock.Object, followersDalMock.Object, settings, loggerMock.Object); + var task = new SendTweetsToSharedInboxTask( + activityPubService.Object, + statusServiceMock.Object, + followersDalMock.Object, + settings, + loggerMock.Object + ); await task.ExecuteAsync(tweets.ToArray(), twitterUser, host, followers.ToArray()); #region Validations @@ -137,18 +146,11 @@ namespace BirdsiteLive.Pipeline.Tests.Processors.SubTasks }; var noteId = "noteId"; - var note = new Note() - { - id = noteId - }; + var note = new Note() { id = noteId }; var twitterHandle = "Test"; var twitterUserId = 7; - var twitterUser = new SyncTwitterUser - { - Id = twitterUserId, - Acct = twitterHandle - }; + var twitterUser = new SyncTwitterUser { Id = twitterUserId, Acct = twitterHandle }; var host = "domain.ext"; var inbox = "/inbox"; @@ -177,10 +179,7 @@ namespace BirdsiteLive.Pipeline.Tests.Processors.SubTasks } }; - var settings = new InstanceSettings - { - PublishReplies = false - }; + var settings = new InstanceSettings { PublishReplies = false }; #endregion #region Mocks @@ -193,15 +192,29 @@ namespace BirdsiteLive.Pipeline.Tests.Processors.SubTasks foreach (var follower in followers) { followersDalMock - .Setup(x => x.UpdateFollowerAsync( - It.Is(y => y.Id == follower.Id && y.FollowingsSyncStatus[twitterUserId] == tweetId))) + .Setup( + x => + x.UpdateFollowerAsync( + It.Is( + y => + y.Id == follower.Id + && y.FollowingsSyncStatus[twitterUserId] == tweetId + ) + ) + ) .Returns(Task.CompletedTask); } var loggerMock = new Mock>(); #endregion - var task = new SendTweetsToSharedInboxTask(activityPubService.Object, statusServiceMock.Object, followersDalMock.Object, settings, loggerMock.Object); + var task = new SendTweetsToSharedInboxTask( + activityPubService.Object, + statusServiceMock.Object, + followersDalMock.Object, + settings, + loggerMock.Object + ); await task.ExecuteAsync(tweets.ToArray(), twitterUser, host, followers.ToArray()); #region Validations @@ -227,18 +240,11 @@ namespace BirdsiteLive.Pipeline.Tests.Processors.SubTasks }; var noteId = "noteId"; - var note = new Note() - { - id = noteId - }; + var note = new Note() { id = noteId }; var twitterHandle = "Test"; var twitterUserId = 7; - var twitterUser = new SyncTwitterUser - { - Id = twitterUserId, - Acct = twitterHandle - }; + var twitterUser = new SyncTwitterUser { Id = twitterUserId, Acct = twitterHandle }; var host = "domain.ext"; var inbox = "/inbox"; @@ -267,28 +273,33 @@ namespace BirdsiteLive.Pipeline.Tests.Processors.SubTasks } }; - var settings = new InstanceSettings - { - PublishReplies = false - }; + var settings = new InstanceSettings { PublishReplies = false }; #endregion #region Mocks var activityPubService = new Mock(MockBehavior.Strict); activityPubService - .Setup(x => x.PostNewNoteActivity( - It.Is(y => y.id == noteId), - It.Is(y => y == twitterHandle), - It.Is(y => y == tweetId.ToString()), - It.Is(y => y == host), - It.Is(y => y == inbox))) + .Setup( + x => + x.PostNewNoteActivity( + It.Is(y => y.id == noteId), + It.Is(y => y == twitterHandle), + It.Is(y => y == tweetId.ToString()), + It.Is(y => y == host), + It.Is(y => y == inbox) + ) + ) .Returns(Task.CompletedTask); var statusServiceMock = new Mock(MockBehavior.Strict); statusServiceMock - .Setup(x => x.GetStatus( - It.Is(y => y == twitterHandle), - It.Is(y => y.Id == tweetId))) + .Setup( + x => + x.GetStatus( + It.Is(y => y == twitterHandle), + It.Is(y => y.Id == tweetId) + ) + ) .Returns(note); var followersDalMock = new Mock(MockBehavior.Strict); @@ -296,15 +307,29 @@ namespace BirdsiteLive.Pipeline.Tests.Processors.SubTasks foreach (var follower in followers) { followersDalMock - .Setup(x => x.UpdateFollowerAsync( - It.Is(y => y.Id == follower.Id && y.FollowingsSyncStatus[twitterUserId] == tweetId))) + .Setup( + x => + x.UpdateFollowerAsync( + It.Is( + y => + y.Id == follower.Id + && y.FollowingsSyncStatus[twitterUserId] == tweetId + ) + ) + ) .Returns(Task.CompletedTask); } var loggerMock = new Mock>(); #endregion - var task = new SendTweetsToSharedInboxTask(activityPubService.Object, statusServiceMock.Object, followersDalMock.Object, settings, loggerMock.Object); + var task = new SendTweetsToSharedInboxTask( + activityPubService.Object, + statusServiceMock.Object, + followersDalMock.Object, + settings, + loggerMock.Object + ); await task.ExecuteAsync(tweets.ToArray(), twitterUser, host, followers.ToArray()); #region Validations @@ -330,18 +355,11 @@ namespace BirdsiteLive.Pipeline.Tests.Processors.SubTasks }; var noteId = "noteId"; - var note = new Note() - { - id = noteId - }; + var note = new Note() { id = noteId }; var twitterHandle = "Test"; var twitterUserId = 7; - var twitterUser = new SyncTwitterUser - { - Id = twitterUserId, - Acct = twitterHandle - }; + var twitterUser = new SyncTwitterUser { Id = twitterUserId, Acct = twitterHandle }; var host = "domain.ext"; var inbox = "/inbox"; @@ -370,28 +388,33 @@ namespace BirdsiteLive.Pipeline.Tests.Processors.SubTasks } }; - var settings = new InstanceSettings - { - PublishReplies = true - }; + var settings = new InstanceSettings { PublishReplies = true }; #endregion #region Mocks var activityPubService = new Mock(MockBehavior.Strict); activityPubService - .Setup(x => x.PostNewNoteActivity( - It.Is(y => y.id == noteId), - It.Is(y => y == twitterHandle), - It.Is(y => y == tweetId.ToString()), - It.Is(y => y == host), - It.Is(y => y == inbox))) + .Setup( + x => + x.PostNewNoteActivity( + It.Is(y => y.id == noteId), + It.Is(y => y == twitterHandle), + It.Is(y => y == tweetId.ToString()), + It.Is(y => y == host), + It.Is(y => y == inbox) + ) + ) .Returns(Task.CompletedTask); var statusServiceMock = new Mock(MockBehavior.Strict); statusServiceMock - .Setup(x => x.GetStatus( - It.Is(y => y == twitterHandle), - It.Is(y => y.Id == tweetId))) + .Setup( + x => + x.GetStatus( + It.Is(y => y == twitterHandle), + It.Is(y => y.Id == tweetId) + ) + ) .Returns(note); var followersDalMock = new Mock(MockBehavior.Strict); @@ -399,15 +422,29 @@ namespace BirdsiteLive.Pipeline.Tests.Processors.SubTasks foreach (var follower in followers) { followersDalMock - .Setup(x => x.UpdateFollowerAsync( - It.Is(y => y.Id == follower.Id && y.FollowingsSyncStatus[twitterUserId] == tweetId))) + .Setup( + x => + x.UpdateFollowerAsync( + It.Is( + y => + y.Id == follower.Id + && y.FollowingsSyncStatus[twitterUserId] == tweetId + ) + ) + ) .Returns(Task.CompletedTask); } var loggerMock = new Mock>(); #endregion - var task = new SendTweetsToSharedInboxTask(activityPubService.Object, statusServiceMock.Object, followersDalMock.Object, settings, loggerMock.Object); + var task = new SendTweetsToSharedInboxTask( + activityPubService.Object, + statusServiceMock.Object, + followersDalMock.Object, + settings, + loggerMock.Object + ); await task.ExecuteAsync(tweets.ToArray(), twitterUser, host, followers.ToArray()); #region Validations @@ -427,19 +464,12 @@ namespace BirdsiteLive.Pipeline.Tests.Processors.SubTasks var tweets = new List(); foreach (var tweetId in new[] { tweetId1, tweetId2, tweetId3 }) { - tweets.Add(new ExtractedTweet - { - Id = tweetId - }); + tweets.Add(new ExtractedTweet { Id = tweetId }); } var twitterHandle = "Test"; var twitterUserId = 7; - var twitterUser = new SyncTwitterUser - { - Id = twitterUserId, - Acct = twitterHandle - }; + var twitterUser = new SyncTwitterUser { Id = twitterUserId, Acct = twitterHandle }; var host = "domain.ext"; var inbox = "/inbox"; @@ -450,28 +480,25 @@ namespace BirdsiteLive.Pipeline.Tests.Processors.SubTasks Id = 1, Host = host, SharedInboxRoute = inbox, - FollowingsSyncStatus = new Dictionary {{twitterUserId, 10}} + FollowingsSyncStatus = new Dictionary { { twitterUserId, 10 } } }, new Follower { Id = 2, Host = host, SharedInboxRoute = inbox, - FollowingsSyncStatus = new Dictionary {{twitterUserId, 8}} + FollowingsSyncStatus = new Dictionary { { twitterUserId, 8 } } }, new Follower { Id = 3, Host = host, SharedInboxRoute = inbox, - FollowingsSyncStatus = new Dictionary {{twitterUserId, 7}} + FollowingsSyncStatus = new Dictionary { { twitterUserId, 7 } } } }; - var settings = new InstanceSettings - { - PublishReplies = false - }; + var settings = new InstanceSettings { PublishReplies = false }; #endregion #region Mocks @@ -479,12 +506,16 @@ namespace BirdsiteLive.Pipeline.Tests.Processors.SubTasks foreach (var tweetId in new[] { tweetId2, tweetId3 }) { activityPubService - .Setup(x => x.PostNewNoteActivity( - It.Is(y => y.id == tweetId.ToString()), - It.Is(y => y == twitterHandle), - It.Is(y => y == tweetId.ToString()), - It.Is(y => y == host), - It.Is(y => y == inbox))) + .Setup( + x => + x.PostNewNoteActivity( + It.Is(y => y.id == tweetId.ToString()), + It.Is(y => y == twitterHandle), + It.Is(y => y == tweetId.ToString()), + It.Is(y => y == host), + It.Is(y => y == inbox) + ) + ) .Returns(Task.CompletedTask); } @@ -492,9 +523,13 @@ namespace BirdsiteLive.Pipeline.Tests.Processors.SubTasks foreach (var tweetId in new[] { tweetId2, tweetId3 }) { statusServiceMock - .Setup(x => x.GetStatus( - It.Is(y => y == twitterHandle), - It.Is(y => y.Id == tweetId))) + .Setup( + x => + x.GetStatus( + It.Is(y => y == twitterHandle), + It.Is(y => y.Id == tweetId) + ) + ) .Returns(new Note { id = tweetId.ToString() }); } @@ -503,15 +538,29 @@ namespace BirdsiteLive.Pipeline.Tests.Processors.SubTasks foreach (var follower in followers) { followersDalMock - .Setup(x => x.UpdateFollowerAsync( - It.Is(y => y.Id == follower.Id && y.FollowingsSyncStatus[twitterUserId] == tweetId3))) + .Setup( + x => + x.UpdateFollowerAsync( + It.Is( + y => + y.Id == follower.Id + && y.FollowingsSyncStatus[twitterUserId] == tweetId3 + ) + ) + ) .Returns(Task.CompletedTask); } var loggerMock = new Mock>(); #endregion - var task = new SendTweetsToSharedInboxTask(activityPubService.Object, statusServiceMock.Object, followersDalMock.Object, settings, loggerMock.Object); + var task = new SendTweetsToSharedInboxTask( + activityPubService.Object, + statusServiceMock.Object, + followersDalMock.Object, + settings, + loggerMock.Object + ); await task.ExecuteAsync(tweets.ToArray(), twitterUser, host, followers.ToArray()); #region Validations @@ -532,19 +581,12 @@ namespace BirdsiteLive.Pipeline.Tests.Processors.SubTasks var tweets = new List(); foreach (var tweetId in new[] { tweetId1, tweetId2, tweetId3 }) { - tweets.Add(new ExtractedTweet - { - Id = tweetId - }); + tweets.Add(new ExtractedTweet { Id = tweetId }); } var twitterHandle = "Test"; var twitterUserId = 7; - var twitterUser = new SyncTwitterUser - { - Id = twitterUserId, - Acct = twitterHandle - }; + var twitterUser = new SyncTwitterUser { Id = twitterUserId, Acct = twitterHandle }; var host = "domain.ext"; var inbox = "/inbox"; @@ -555,58 +597,67 @@ namespace BirdsiteLive.Pipeline.Tests.Processors.SubTasks Id = 1, Host = host, SharedInboxRoute = inbox, - FollowingsSyncStatus = new Dictionary {{twitterUserId, 10}} + FollowingsSyncStatus = new Dictionary { { twitterUserId, 10 } } }, new Follower { Id = 2, Host = host, SharedInboxRoute = inbox, - FollowingsSyncStatus = new Dictionary {{twitterUserId, 8}} + FollowingsSyncStatus = new Dictionary { { twitterUserId, 8 } } }, new Follower { Id = 3, Host = host, SharedInboxRoute = inbox, - FollowingsSyncStatus = new Dictionary {{twitterUserId, 7}} + FollowingsSyncStatus = new Dictionary { { twitterUserId, 7 } } } }; - var settings = new InstanceSettings - { - PublishReplies = false - }; + var settings = new InstanceSettings { PublishReplies = false }; #endregion #region Mocks var activityPubService = new Mock(MockBehavior.Strict); activityPubService - .Setup(x => x.PostNewNoteActivity( - It.Is(y => y.id == tweetId2.ToString()), - It.Is(y => y == twitterHandle), - It.Is(y => y == tweetId2.ToString()), - It.Is(y => y == host), - It.Is(y => y == inbox))) + .Setup( + x => + x.PostNewNoteActivity( + It.Is(y => y.id == tweetId2.ToString()), + It.Is(y => y == twitterHandle), + It.Is(y => y == tweetId2.ToString()), + It.Is(y => y == host), + It.Is(y => y == inbox) + ) + ) .Returns(Task.CompletedTask); activityPubService - .Setup(x => x.PostNewNoteActivity( - It.Is(y => y.id == tweetId3.ToString()), - It.Is(y => y == twitterHandle), - It.Is(y => y == tweetId3.ToString()), - It.Is(y => y == host), - It.Is(y => y == inbox))) + .Setup( + x => + x.PostNewNoteActivity( + It.Is(y => y.id == tweetId3.ToString()), + It.Is(y => y == twitterHandle), + It.Is(y => y == tweetId3.ToString()), + It.Is(y => y == host), + It.Is(y => y == inbox) + ) + ) .Throws(new HttpRequestException()); var statusServiceMock = new Mock(MockBehavior.Strict); foreach (var tweetId in new[] { tweetId2, tweetId3 }) { statusServiceMock - .Setup(x => x.GetStatus( - It.Is(y => y == twitterHandle), - It.Is(y => y.Id == tweetId))) + .Setup( + x => + x.GetStatus( + It.Is(y => y == twitterHandle), + It.Is(y => y.Id == tweetId) + ) + ) .Returns(new Note { id = tweetId.ToString() }); } @@ -615,15 +666,29 @@ namespace BirdsiteLive.Pipeline.Tests.Processors.SubTasks foreach (var follower in followers) { followersDalMock - .Setup(x => x.UpdateFollowerAsync( - It.Is(y => y.Id == follower.Id && y.FollowingsSyncStatus[twitterUserId] == tweetId2))) + .Setup( + x => + x.UpdateFollowerAsync( + It.Is( + y => + y.Id == follower.Id + && y.FollowingsSyncStatus[twitterUserId] == tweetId2 + ) + ) + ) .Returns(Task.CompletedTask); } var loggerMock = new Mock>(); #endregion - var task = new SendTweetsToSharedInboxTask(activityPubService.Object, statusServiceMock.Object, followersDalMock.Object, settings, loggerMock.Object); + var task = new SendTweetsToSharedInboxTask( + activityPubService.Object, + statusServiceMock.Object, + followersDalMock.Object, + settings, + loggerMock.Object + ); try { @@ -644,27 +709,14 @@ namespace BirdsiteLive.Pipeline.Tests.Processors.SubTasks { #region Stubs var tweetId = 10; - var tweets = new List - { - new ExtractedTweet - { - Id = tweetId, - } - }; + var tweets = new List { new ExtractedTweet { Id = tweetId, } }; var noteId = "noteId"; - var note = new Note() - { - id = noteId - }; + var note = new Note() { id = noteId }; var twitterHandle = "Test"; var twitterUserId = 7; - var twitterUser = new SyncTwitterUser - { - Id = twitterUserId, - Acct = twitterHandle - }; + var twitterUser = new SyncTwitterUser { Id = twitterUserId, Acct = twitterHandle }; var host = "domain.ext"; var inbox = "/inbox"; @@ -693,10 +745,7 @@ namespace BirdsiteLive.Pipeline.Tests.Processors.SubTasks } }; - var settings = new InstanceSettings - { - PublishReplies = false - }; + var settings = new InstanceSettings { PublishReplies = false }; #endregion #region Mocks @@ -704,9 +753,13 @@ namespace BirdsiteLive.Pipeline.Tests.Processors.SubTasks var statusServiceMock = new Mock(MockBehavior.Strict); statusServiceMock - .Setup(x => x.GetStatus( - It.Is(y => y == twitterHandle), - It.Is(y => y.Id == tweetId))) + .Setup( + x => + x.GetStatus( + It.Is(y => y == twitterHandle), + It.Is(y => y.Id == tweetId) + ) + ) .Throws(new ArgumentException("Invalid pattern blabla at offset 9")); var followersDalMock = new Mock(MockBehavior.Strict); @@ -714,15 +767,29 @@ namespace BirdsiteLive.Pipeline.Tests.Processors.SubTasks foreach (var follower in followers) { followersDalMock - .Setup(x => x.UpdateFollowerAsync( - It.Is(y => y.Id == follower.Id && y.FollowingsSyncStatus[twitterUserId] == tweetId))) + .Setup( + x => + x.UpdateFollowerAsync( + It.Is( + y => + y.Id == follower.Id + && y.FollowingsSyncStatus[twitterUserId] == tweetId + ) + ) + ) .Returns(Task.CompletedTask); } var loggerMock = new Mock>(); #endregion - var task = new SendTweetsToSharedInboxTask(activityPubService.Object, statusServiceMock.Object, followersDalMock.Object, settings, loggerMock.Object); + var task = new SendTweetsToSharedInboxTask( + activityPubService.Object, + statusServiceMock.Object, + followersDalMock.Object, + settings, + loggerMock.Object + ); await task.ExecuteAsync(tweets.ToArray(), twitterUser, host, followers.ToArray()); #region Validations @@ -738,21 +805,11 @@ namespace BirdsiteLive.Pipeline.Tests.Processors.SubTasks { #region Stubs var tweetId = 10; - var tweets = new List - { - new ExtractedTweet - { - Id = tweetId, - } - }; + var tweets = new List { new ExtractedTweet { Id = tweetId, } }; var twitterHandle = "Test"; var twitterUserId = 7; - var twitterUser = new SyncTwitterUser - { - Id = twitterUserId, - Acct = twitterHandle - }; + var twitterUser = new SyncTwitterUser { Id = twitterUserId, Acct = twitterHandle }; var host = "domain.ext"; var inbox = "/inbox"; @@ -781,10 +838,7 @@ namespace BirdsiteLive.Pipeline.Tests.Processors.SubTasks } }; - var settings = new InstanceSettings - { - PublishReplies = false - }; + var settings = new InstanceSettings { PublishReplies = false }; #endregion #region Mocks @@ -792,9 +846,13 @@ namespace BirdsiteLive.Pipeline.Tests.Processors.SubTasks var statusServiceMock = new Mock(MockBehavior.Strict); statusServiceMock - .Setup(x => x.GetStatus( - It.Is(y => y == twitterHandle), - It.Is(y => y.Id == tweetId))) + .Setup( + x => + x.GetStatus( + It.Is(y => y == twitterHandle), + It.Is(y => y.Id == tweetId) + ) + ) .Throws(new ArgumentException()); var followersDalMock = new Mock(MockBehavior.Strict); @@ -802,12 +860,17 @@ namespace BirdsiteLive.Pipeline.Tests.Processors.SubTasks var loggerMock = new Mock>(); #endregion - var task = new SendTweetsToSharedInboxTask(activityPubService.Object, statusServiceMock.Object, followersDalMock.Object, settings, loggerMock.Object); + var task = new SendTweetsToSharedInboxTask( + activityPubService.Object, + statusServiceMock.Object, + followersDalMock.Object, + settings, + loggerMock.Object + ); try { await task.ExecuteAsync(tweets.ToArray(), twitterUser, host, followers.ToArray()); - } finally { @@ -819,4 +882,4 @@ namespace BirdsiteLive.Pipeline.Tests.Processors.SubTasks } } } -} \ No newline at end of file +} diff --git a/src/Tests/BirdsiteLive.Pipeline.Tests/StatusPublicationPipelineTests.cs b/src/Tests/BirdsiteLive.Pipeline.Tests/StatusPublicationPipelineTests.cs index 81eeb59..c44a2ea 100644 --- a/src/Tests/BirdsiteLive.Pipeline.Tests/StatusPublicationPipelineTests.cs +++ b/src/Tests/BirdsiteLive.Pipeline.Tests/StatusPublicationPipelineTests.cs @@ -1,10 +1,13 @@ -using System.Threading; +using System.Threading; using System.Threading.Tasks; using System.Threading.Tasks.Dataflow; + using BirdsiteLive.DAL.Models; using BirdsiteLive.Pipeline.Contracts; + using Microsoft.Extensions.Logging; using Microsoft.VisualStudio.TestTools.UnitTesting; + using Moq; namespace BirdsiteLive.Pipeline.Tests @@ -20,22 +23,42 @@ namespace BirdsiteLive.Pipeline.Tests #endregion #region Mocks - var retrieveTwitterUsersProcessor = new Mock(MockBehavior.Strict); + var retrieveTwitterUsersProcessor = new Mock( + MockBehavior.Strict + ); retrieveTwitterUsersProcessor - .Setup(x => x.GetTwitterUsersAsync( - It.IsAny>(), - It.IsAny())) + .Setup( + x => + x.GetTwitterUsersAsync( + It.IsAny>(), + It.IsAny() + ) + ) .Returns(Task.Delay(0)); - var refreshTwitterUserStatusProcessor = new Mock(MockBehavior.Strict); + var refreshTwitterUserStatusProcessor = new Mock( + MockBehavior.Strict + ); var retrieveTweetsProcessor = new Mock(MockBehavior.Strict); - var retrieveFollowersProcessor = new Mock(MockBehavior.Strict); - var sendTweetsToFollowersProcessor = new Mock(MockBehavior.Strict); + var retrieveFollowersProcessor = new Mock( + MockBehavior.Strict + ); + var sendTweetsToFollowersProcessor = new Mock( + MockBehavior.Strict + ); var saveProgressionProcessor = new Mock(MockBehavior.Strict); var logger = new Mock>(); #endregion - var pipeline = new StatusPublicationPipeline(retrieveTweetsProcessor.Object, retrieveTwitterUsersProcessor.Object, retrieveFollowersProcessor.Object, sendTweetsToFollowersProcessor.Object, saveProgressionProcessor.Object, refreshTwitterUserStatusProcessor.Object, logger.Object); + var pipeline = new StatusPublicationPipeline( + retrieveTweetsProcessor.Object, + retrieveTwitterUsersProcessor.Object, + retrieveFollowersProcessor.Object, + sendTweetsToFollowersProcessor.Object, + saveProgressionProcessor.Object, + refreshTwitterUserStatusProcessor.Object, + logger.Object + ); await pipeline.ExecuteAsync(ct.Token); #region Validations @@ -48,4 +71,4 @@ namespace BirdsiteLive.Pipeline.Tests #endregion } } -} \ No newline at end of file +} diff --git a/src/Tests/BirdsiteLive.Pipeline.Tests/Tools/MaxUsersNumberProviderTests.cs b/src/Tests/BirdsiteLive.Pipeline.Tests/Tools/MaxUsersNumberProviderTests.cs index c2f52d0..4424d40 100644 --- a/src/Tests/BirdsiteLive.Pipeline.Tests/Tools/MaxUsersNumberProviderTests.cs +++ b/src/Tests/BirdsiteLive.Pipeline.Tests/Tools/MaxUsersNumberProviderTests.cs @@ -1,8 +1,11 @@ -using System.Threading.Tasks; +using System.Threading.Tasks; + using BirdsiteLive.Common.Settings; using BirdsiteLive.DAL.Contracts; using BirdsiteLive.Pipeline.Tools; + using Microsoft.VisualStudio.TestTools.UnitTesting; + using Moq; namespace BirdsiteLive.Pipeline.Tests.Tools @@ -14,21 +17,16 @@ namespace BirdsiteLive.Pipeline.Tests.Tools public async Task GetMaxUsersNumberAsync_WarmUp_Test() { #region Stubs - var settings = new InstanceSettings - { - MaxUsersCapacity = 1000 - }; + var settings = new InstanceSettings { MaxUsersCapacity = 1000 }; #endregion #region Mocks var twitterUserDalMock = new Mock(MockBehavior.Strict); - twitterUserDalMock - .Setup(x => x.GetTwitterUsersCountAsync()) - .ReturnsAsync(1000); + twitterUserDalMock.Setup(x => x.GetTwitterUsersCountAsync()).ReturnsAsync(1000); #endregion var provider = new MaxUsersNumberProvider(settings, twitterUserDalMock.Object); - + var result = await provider.GetMaxUsersNumberAsync(); Assert.AreEqual(200, result); @@ -40,13 +38,13 @@ namespace BirdsiteLive.Pipeline.Tests.Tools result = await provider.GetMaxUsersNumberAsync(); Assert.AreEqual(200, result); - + result = await provider.GetMaxUsersNumberAsync(); Assert.AreEqual(200, result); - + result = await provider.GetMaxUsersNumberAsync(); Assert.AreEqual(1000, result); - + #region Validations twitterUserDalMock.VerifyAll(); #endregion @@ -56,17 +54,12 @@ namespace BirdsiteLive.Pipeline.Tests.Tools public async Task GetMaxUsersNumberAsync_NoWarmUp_Test() { #region Stubs - var settings = new InstanceSettings - { - MaxUsersCapacity = 1000 - }; + var settings = new InstanceSettings { MaxUsersCapacity = 1000 }; #endregion #region Mocks var twitterUserDalMock = new Mock(MockBehavior.Strict); - twitterUserDalMock - .Setup(x => x.GetTwitterUsersCountAsync()) - .ReturnsAsync(199); + twitterUserDalMock.Setup(x => x.GetTwitterUsersCountAsync()).ReturnsAsync(199); #endregion var provider = new MaxUsersNumberProvider(settings, twitterUserDalMock.Object); @@ -79,4 +72,4 @@ namespace BirdsiteLive.Pipeline.Tests.Tools #endregion } } -} \ No newline at end of file +}