diff --git a/.editorconfig b/.editorconfig index b32d96da..0fb81395 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,155 +1,257 @@ -# 若要了解有关 .editorconfig 的详细信息,请参阅 https://aka.ms/editorconfigdocs -############################### -# Core EditorConfig Options # -############################### -root = true -# All files -[*] -indent_style = space +# Rules in this file were initially inferred by Visual Studio IntelliCode from the C:\Users\chr11\OneDrive\repos\ASF_Plugins\ASFEnhance\ASFEnhance\ codebase based on best match to current usage at 2021-7-26 +# You can modify the rules from these initially generated values to suit your own policies +# You can learn more about editorconfig here: https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-code-style-settings-reference +[*.cs] -# XML project files -[*.{csproj,vbproj,vcxproj,vcxproj.filters,proj,projitems,shproj}] -indent_size = 2 -# XML config files -[*.{props,targets,ruleset,config,nuspec,resx,vsixmanifest,vsct}] -indent_size = 2 +#Core editorconfig formatting - indentation -# Code files -[*.{cs,csx,vb,vbx}] -indent_size = 4 -insert_final_newline = true -charset = utf-8-bom -############################### -# .NET Coding Conventions # -############################### -[*.{cs,vb}] -# Organize usings -dotnet_sort_system_directives_first = true -# this. preferences -dotnet_style_qualification_for_field = false:silent -dotnet_style_qualification_for_property = false:silent -dotnet_style_qualification_for_method = false:silent -dotnet_style_qualification_for_event = false:silent -# Language keywords vs BCL types preferences -dotnet_style_predefined_type_for_locals_parameters_members = true:silent -dotnet_style_predefined_type_for_member_access = true:silent -# Parentheses preferences -dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:silent -dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:silent -dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:silent -dotnet_style_parentheses_in_other_operators = always_for_clarity:silent -# Modifier preferences -dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent -dotnet_style_readonly_field = true:suggestion -# Expression-level preferences -dotnet_style_object_initializer = true:suggestion -dotnet_style_collection_initializer = true:suggestion -dotnet_style_explicit_tuple_names = true:suggestion -dotnet_style_null_propagation = true:suggestion -dotnet_style_coalesce_expression = true:suggestion -dotnet_style_prefer_is_null_check_over_reference_equality_method = true:silent -dotnet_style_prefer_inferred_tuple_names = true:suggestion -dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion -dotnet_style_prefer_auto_properties = true:silent -dotnet_style_prefer_conditional_expression_over_assignment = true:silent -dotnet_style_prefer_conditional_expression_over_return = true:silent -############################### -# Naming Conventions # -############################### -# Style Definitions -dotnet_naming_style.pascal_case_style.capitalization = pascal_case -# Use PascalCase for constant fields -dotnet_naming_rule.constant_fields_should_be_pascal_case.severity = suggestion -dotnet_naming_rule.constant_fields_should_be_pascal_case.symbols = constant_fields -dotnet_naming_rule.constant_fields_should_be_pascal_case.style = pascal_case_style -dotnet_naming_symbols.constant_fields.applicable_kinds = field -dotnet_naming_symbols.constant_fields.applicable_accessibilities = * -dotnet_naming_symbols.constant_fields.required_modifiers = const -dotnet_code_quality_unused_parameters = all:suggestion -end_of_line = crlf -tab_width = 4 -dotnet_style_operator_placement_when_wrapping = beginning_of_line -dotnet_style_allow_multiple_blank_lines_experimental = true:silent -dotnet_style_allow_statement_immediately_after_block_experimental = true:silent -############################### -# C# Coding Conventions # -############################### -[*.cs] -# var preferences -csharp_style_var_for_built_in_types = true:silent -csharp_style_var_when_type_is_apparent = true:silent -csharp_style_var_elsewhere = true:silent -# Expression-bodied members -csharp_style_expression_bodied_methods = false:silent -csharp_style_expression_bodied_constructors = false:silent -csharp_style_expression_bodied_operators = false:silent -csharp_style_expression_bodied_properties = true:silent -csharp_style_expression_bodied_indexers = true:silent -csharp_style_expression_bodied_accessors = true:silent -# Pattern matching preferences -csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion -csharp_style_pattern_matching_over_as_with_null_check = true:suggestion -# Null-checking preferences -csharp_style_throw_expression = true:suggestion -csharp_style_conditional_delegate_call = true:suggestion -# Modifier preferences -csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:suggestion -# Expression-level preferences -csharp_prefer_braces = true:silent -csharp_style_deconstructed_variable_declaration = true:suggestion -csharp_prefer_simple_default_expression = true:suggestion -csharp_style_pattern_local_over_anonymous_function = true:suggestion -csharp_style_inlined_variable_declaration = true:suggestion -############################### -# C# Formatting Rules # -############################### -# New line preferences -csharp_new_line_before_open_brace = all +#use soft tabs (spaces) for indentation +indent_style = space + +#Formatting - new line options + +#place else statements on a new line csharp_new_line_before_else = true -csharp_new_line_before_catch = true -csharp_new_line_before_finally = true -csharp_new_line_before_members_in_object_initializers = true -csharp_new_line_before_members_in_anonymous_types = true -csharp_new_line_between_query_expression_clauses = true -# Indentation preferences -csharp_indent_case_contents = true -csharp_indent_switch_labels = true -csharp_indent_labels = flush_left -# Space preferences +#require members of object initializers to be on the same line +csharp_new_line_before_members_in_object_initializers = false +#require braces to be on a new line for types, control_blocks, and methods (also known as "Allman" style) +csharp_new_line_before_open_brace = types, control_blocks, methods + +#Formatting - organize using options + +#do not place System.* using directives before other using directives +dotnet_sort_system_directives_first = false + +#Formatting - spacing options + +#require NO space between a cast and the value csharp_space_after_cast = false +#require a space after a keyword in a control flow statement such as a for loop csharp_space_after_keywords_in_control_flow_statements = true +#remove space within empty argument list parentheses +csharp_space_between_method_call_empty_parameter_list_parentheses = false +#remove space between method call name and opening parenthesis +csharp_space_between_method_call_name_and_opening_parenthesis = false +#do not place space characters after the opening parenthesis and before the closing parenthesis of a method call csharp_space_between_method_call_parameter_list_parentheses = false +#place a space character after the opening parenthesis and before the closing parenthesis of a method declaration parameter list. csharp_space_between_method_declaration_parameter_list_parentheses = false -csharp_space_between_parentheses = false -csharp_space_before_colon_in_inheritance_clause = true -csharp_space_after_colon_in_inheritance_clause = true -csharp_space_around_binary_operators = before_and_after -csharp_space_between_method_declaration_empty_parameter_list_parentheses = false -csharp_space_between_method_call_name_and_opening_parenthesis = false -csharp_space_between_method_call_empty_parameter_list_parentheses = false -# Wrapping preferences -csharp_preserve_single_line_statements = true -csharp_preserve_single_line_blocks = true + +#Style - Code block preferences + +#prefer curly braces even for one line of code +csharp_prefer_braces = true:warning + +#Style - expression bodied member options + +#prefer block bodies for methods +csharp_style_expression_bodied_methods = true:warning +#prefer expression-bodied members for properties +csharp_style_expression_bodied_properties = true:warning + +#Style - expression level options + +#prefer out variables to be declared inline in the argument list of a method call when possible +csharp_style_inlined_variable_declaration = true:suggestion +#prefer the language keyword for member access expressions, instead of the type name, for types that have a keyword to represent them +dotnet_style_predefined_type_for_member_access = true:suggestion + +#Style - implicit and explicit types + +#prefer explicit type over var in all cases, unless overridden by another code style rule +csharp_style_var_elsewhere = false:warning +#prefer explicit type over var to declare variables with built-in system types such as int +csharp_style_var_for_built_in_types = false:warning + +#Style - language keyword and framework type options + +#prefer the language keyword for local variables, method parameters, and class members, instead of the type name, for types that have a keyword to represent them +dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion + +#Style - modifier options + +#prefer accessibility modifiers to be declared except for public interface members. This will currently not differ from always and will act as future proofing for if C# adds default interface methods. +dotnet_style_require_accessibility_modifiers = for_non_interface_members:suggestion + +#Style - Modifier preferences + +#when this rule is set to a list of modifiers, prefer the specified ordering. +csharp_preferred_modifier_order = public,internal,static,async,sealed:silent + +#Style - qualification options + +#prefer fields to be prefaced with this. in C# or Me. in Visual Basic +dotnet_style_qualification_for_field = true:suggestion +#prefer properties not to be prefaced with this. or Me. in Visual Basic +dotnet_style_qualification_for_property = false:suggestion +insert_final_newline=true + +# CS8632: ֻ "#nullable" עڵĴʹÿΪ null ͵ע͡ +dotnet_diagnostic.CS8632.severity = suggestion + +[*.cs] +#### ʽ #### + +# + +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 + +# Ź淶 + +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 = + +# ʽ + +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_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.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 csharp_using_directive_placement = outside_namespace:silent -csharp_style_expression_bodied_lambdas = true:silent -csharp_style_expression_bodied_local_functions = false:silent -csharp_prefer_simple_using_statement = true:suggestion +csharp_style_expression_bodied_constructors = true:warning +csharp_style_expression_bodied_operators = true:warning +csharp_style_expression_bodied_indexers = true:warning +csharp_style_expression_bodied_accessors = true:warning +csharp_style_expression_bodied_lambdas = true:warning +csharp_style_expression_bodied_local_functions = true:warning +csharp_style_conditional_delegate_call = true:warning +csharp_style_prefer_parameter_null_checking = true:suggestion +csharp_style_var_when_type_is_apparent = false:warning +csharp_prefer_simple_using_statement = true:warning csharp_style_namespace_declarations = block_scoped:suggestion csharp_style_prefer_method_group_conversion = true:silent + +# IDE0036: η +dotnet_diagnostic.IDE0036.severity = silent csharp_style_prefer_top_level_statements = true:silent -csharp_prefer_static_local_function = true:suggestion +csharp_prefer_static_local_function = true:warning csharp_style_prefer_readonly_struct = true:suggestion csharp_style_allow_embedded_statements_on_same_line_experimental = true:silent +csharp_space_around_binary_operators = before_and_after csharp_style_allow_blank_lines_between_consecutive_braces_experimental = true:silent +csharp_style_pattern_matching_over_as_with_null_check = true:suggestion +csharp_style_prefer_null_check_over_type_check = true:suggestion +csharp_indent_labels = one_less_than_current +csharp_space_between_parentheses = false csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = true:silent csharp_style_prefer_switch_expression = true:suggestion csharp_style_prefer_pattern_matching = true:silent -csharp_style_prefer_not_pattern = true:suggestion +csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion csharp_style_prefer_extended_property_pattern = true:suggestion -############################### -# VB Coding Conventions # -############################### +csharp_style_prefer_not_pattern = true:suggestion +csharp_style_allow_blank_line_after_token_in_arrow_expression_clause_experimental = true:silent +csharp_style_allow_blank_line_after_token_in_conditional_expression_experimental = true:silent + [*.vb] -# Modifier preferences -visual_basic_preferred_modifier_order = Partial,Default,Private,Protected,Public,Friend,NotOverridable,Overridable,MustOverride,Overloads,Overrides,MustInherit,NotInheritable,Static,Shared,Shadows,ReadOnly,WriteOnly,Dim,Const,WithEvents,Widening,Narrowing,Custom,Async:suggestion +#### ʽ #### + +# + +dotnet_naming_rule.interface_should_be__i_ʼ.severity = suggestion +dotnet_naming_rule.interface_should_be__i_ʼ.symbols = interface +dotnet_naming_rule.interface_should_be__i_ʼ.style = _i_ʼ + +dotnet_naming_rule._should_be_˹ƴд.severity = suggestion +dotnet_naming_rule._should_be_˹ƴд.symbols = +dotnet_naming_rule._should_be_˹ƴд.style = ˹ƴд + +dotnet_naming_rule.ֶγԱ_should_be_˹ƴд.severity = suggestion +dotnet_naming_rule.ֶγԱ_should_be_˹ƴд.symbols = ֶγԱ +dotnet_naming_rule.ֶγԱ_should_be_˹ƴд.style = ˹ƴд + +# Ź淶 + +dotnet_naming_symbols.interface.applicable_kinds = interface +dotnet_naming_symbols.interface.applicable_accessibilities = public, friend, private, protected, protected_friend, private_protected +dotnet_naming_symbols.interface.required_modifiers = + +dotnet_naming_symbols..applicable_kinds = class, struct, interface, enum +dotnet_naming_symbols..applicable_accessibilities = public, friend, private, protected, protected_friend, private_protected +dotnet_naming_symbols..required_modifiers = + +dotnet_naming_symbols.ֶγԱ.applicable_kinds = property, event, method +dotnet_naming_symbols.ֶγԱ.applicable_accessibilities = public, friend, private, protected, protected_friend, private_protected +dotnet_naming_symbols.ֶγԱ.required_modifiers = + +# ʽ + +dotnet_naming_style._i_ʼ.required_prefix = I +dotnet_naming_style._i_ʼ.required_suffix = +dotnet_naming_style._i_ʼ.word_separator = +dotnet_naming_style._i_ʼ.capitalization = pascal_case + +dotnet_naming_style.˹ƴд.required_prefix = +dotnet_naming_style.˹ƴд.required_suffix = +dotnet_naming_style.˹ƴд.word_separator = +dotnet_naming_style.˹ƴд.capitalization = pascal_case + +dotnet_naming_style.˹ƴд.required_prefix = +dotnet_naming_style.˹ƴд.required_suffix = +dotnet_naming_style.˹ƴд.word_separator = +dotnet_naming_style.˹ƴд.capitalization = pascal_case + +[*.{cs,vb}] +end_of_line = crlf +dotnet_style_qualification_for_field = false:warning +dotnet_style_qualification_for_property = false:warning +dotnet_style_qualification_for_method = false:warning +dotnet_style_qualification_for_event = false:warning + +# Default severity for analyzer diagnostics with category 'Style' +dotnet_analyzer_diagnostic.category-Style.severity = silent +dotnet_style_require_accessibility_modifiers = always:warning +dotnet_code_quality_unused_parameters = all:warning +dotnet_style_readonly_field = true:suggestion +dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:silent +dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:silent +dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:silent +dotnet_style_parentheses_in_other_operators = never_if_unnecessary:silent +dotnet_style_allow_multiple_blank_lines_experimental = true:silent +dotnet_style_allow_statement_immediately_after_block_experimental = true:silent +tab_width = 4 +indent_size = 4 +dotnet_style_null_propagation = true:suggestion +dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion +dotnet_style_operator_placement_when_wrapping = beginning_of_line +dotnet_style_coalesce_expression = true:suggestion +dotnet_style_prefer_auto_properties = true:silent +dotnet_style_object_initializer = true:suggestion +dotnet_style_prefer_simplified_boolean_expressions = true:suggestion +dotnet_style_collection_initializer = true:suggestion +dotnet_style_prefer_conditional_expression_over_assignment = true:silent +dotnet_style_prefer_conditional_expression_over_return = true:silent +dotnet_style_namespace_match_folder = true:suggestion +dotnet_style_explicit_tuple_names = true:suggestion +dotnet_style_prefer_inferred_tuple_names = true:suggestion +dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion +dotnet_style_prefer_compound_assignment = true:suggestion diff --git a/Directory.Build.props b/Directory.Build.props index be1b7626..fa56163d 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,6 +1,6 @@ - 2.0.25.1 + 2.1.0.0 diff --git a/Directory.Packages.props b/Directory.Packages.props index b99dd242..f03246f4 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -5,14 +5,14 @@ - - - + + + - + - + \ No newline at end of file diff --git a/XinjingdailyBot.Command/AdminCommand.cs b/XinjingdailyBot.Command/AdminCommand.cs index a28af38d..92e56533 100644 --- a/XinjingdailyBot.Command/AdminCommand.cs +++ b/XinjingdailyBot.Command/AdminCommand.cs @@ -1,10 +1,9 @@ -using System.Diagnostics; +using Microsoft.Extensions.Logging; +using SqlSugar; +using System.Diagnostics; using System.Reflection; using System.Runtime.InteropServices; using System.Text; -using Microsoft.Extensions.Logging; -using Microsoft.VisualBasic; -using SqlSugar; using Telegram.Bot; using Telegram.Bot.Types; using Telegram.Bot.Types.Enums; @@ -77,7 +76,7 @@ public AdminCommand( /// /// /// - [TextCmd("GROUPINFO", UserRights.AdminCmd, Description = "获取群组信息")] + [TextCmd("GROUPINFO", EUserRights.AdminCmd, Description = "获取群组信息")] public async Task ResponseGroupInfo(Message message) { var chat = message.Chat; @@ -113,7 +112,7 @@ public async Task ResponseGroupInfo(Message message) /// /// /// - [TextCmd("USERINFO", UserRights.AdminCmd, Alias = "UINFO", Description = "获取用户信息")] + [TextCmd("USERINFO", EUserRights.AdminCmd, Alias = "UINFO", Description = "获取用户信息")] public async Task ResponseUserInfo(Message message, string[] args) { StringBuilder sb = new(); @@ -152,7 +151,7 @@ public async Task ResponseUserInfo(Message message, string[] args) /// /// /// - [TextCmd("BAN", UserRights.AdminCmd, Description = "封禁用户")] + [TextCmd("BAN", EUserRights.AdminCmd, Description = "封禁用户")] public async Task ResponseBan(Users dbUser, Message message, string[] args) { async Task exec() @@ -199,11 +198,10 @@ async Task exec() targetUser.ModifyAt = DateTime.Now; await _userService.Updateable(targetUser).UpdateColumns(x => new { x.IsBan, x.ModifyAt }).ExecuteCommandAsync(); - var record = new BanRecords - { + var record = new BanRecords { UserID = targetUser.UserID, OperatorUID = dbUser.UserID, - Type = BanType.Ban, + Type = EBanType.Ban, BanTime = DateTime.Now, Reason = reason, }; @@ -247,7 +245,7 @@ async Task exec() /// /// /// - [TextCmd("UNBAN", UserRights.AdminCmd, Description = "解封用户")] + [TextCmd("UNBAN", EUserRights.AdminCmd, Description = "解封用户")] public async Task ResponseUnban(Users dbUser, Message message, string[] args) { async Task exec() @@ -294,11 +292,10 @@ async Task exec() targetUser.ModifyAt = DateTime.Now; await _userService.Updateable(targetUser).UpdateColumns(x => new { x.IsBan, x.ModifyAt }).ExecuteCommandAsync(); - var record = new BanRecords - { + var record = new BanRecords { UserID = targetUser.UserID, OperatorUID = dbUser.UserID, - Type = BanType.UnBan, + Type = EBanType.UnBan, BanTime = DateTime.Now, Reason = reason, }; @@ -342,7 +339,7 @@ async Task exec() /// /// /// - [TextCmd("WARN", UserRights.AdminCmd, Description = "警告用户")] + [TextCmd("WARN", EUserRights.AdminCmd, Description = "警告用户")] public async Task ResponseWarning(Users dbUser, Message message, string[] args) { async Task exec() @@ -386,24 +383,23 @@ async Task exec() else { //获取最近一条解封记录 - var lastUnbaned = await _banRecordService.Queryable().Where(x => x.UserID == targetUser.UserID && (x.Type == BanType.UnBan || x.Type == BanType.Ban)) + var lastUnbaned = await _banRecordService.Queryable().Where(x => x.UserID == targetUser.UserID && (x.Type == EBanType.UnBan || x.Type == EBanType.Ban)) .OrderByDescending(x => x.BanTime).FirstAsync(); int warnCount; if (lastUnbaned == null) { - warnCount = await _banRecordService.Queryable().Where(x => x.UserID == targetUser.UserID && x.Type == BanType.Warning).CountAsync(); + warnCount = await _banRecordService.Queryable().Where(x => x.UserID == targetUser.UserID && x.Type == EBanType.Warning).CountAsync(); } else { - warnCount = await _banRecordService.Queryable().Where(x => x.UserID == targetUser.UserID && x.Type == BanType.Warning && x.BanTime >= lastUnbaned.BanTime).CountAsync(); + warnCount = await _banRecordService.Queryable().Where(x => x.UserID == targetUser.UserID && x.Type == EBanType.Warning && x.BanTime >= lastUnbaned.BanTime).CountAsync(); } - var record = new BanRecords - { + var record = new BanRecords { UserID = targetUser.UserID, OperatorUID = dbUser.UserID, - Type = BanType.Warning, + Type = EBanType.Warning, BanTime = DateTime.Now, Reason = reason, }; @@ -420,11 +416,10 @@ async Task exec() if (warnCount >= WarningLimit) { - record = new BanRecords - { + record = new BanRecords { UserID = targetUser.UserID, OperatorUID = 0, - Type = BanType.Ban, + Type = EBanType.Ban, BanTime = DateTime.Now, Reason = "受到警告过多, 自动封禁", }; @@ -480,7 +475,7 @@ async Task exec() /// /// /// - [TextCmd("QUERYBAN", UserRights.AdminCmd, Alias = "QBAN", Description = "查询封禁记录")] + [TextCmd("QUERYBAN", EUserRights.AdminCmd, Alias = "QBAN", Description = "查询封禁记录")] public async Task ResponseQueryBan(Message message, string[] args) { StringBuilder sb = new(); @@ -527,15 +522,14 @@ public async Task ResponseQueryBan(Message message, string[] args) foreach (var record in records) { var date = record.BanTime.ToString("d"); - var operate = record.Type switch - { - BanType.UnBan => "解封", - BanType.Ban => "封禁", - BanType.Warning => "警告", - BanType.GlobalMute => "全局禁言", - BanType.GlobalBan => "全局封禁", - BanType.GlobalUnMute => "撤销全局禁言", - BanType.GlobalUnBan => "撤销全局封禁", + var operate = record.Type switch { + EBanType.UnBan => "解封", + EBanType.Ban => "封禁", + EBanType.Warning => "警告", + EBanType.GlobalMute => "全局禁言", + EBanType.GlobalBan => "全局封禁", + EBanType.GlobalUnMute => "撤销全局禁言", + EBanType.GlobalUnBan => "撤销全局封禁", _ => "未知", }; @@ -564,7 +558,7 @@ public async Task ResponseQueryBan(Message message, string[] args) /// /// /// - [TextCmd("ECHO", UserRights.AdminCmd, Description = "回复用户")] + [TextCmd("ECHO", EUserRights.AdminCmd, Description = "回复用户")] public async Task ResponseEcho(Users dbUser, Message message, string[] args) { var autoDelete = true; @@ -626,7 +620,7 @@ async Task exec() /// /// /// - [TextCmd("SEARCHUSER", UserRights.AdminCmd, Alias = "QUSER", Description = "搜索用户")] + [TextCmd("SEARCHUSER", EUserRights.AdminCmd, Alias = "QUSER", Description = "搜索用户")] public async Task ResponseSearchUser(Users dbUser, Message message, string[] args) { if (!args.Any()) @@ -661,7 +655,7 @@ public async Task ResponseSearchUser(Users dbUser, Message message, string[] arg /// /// /// - [QueryCmd("SEARCHUSER", UserRights.AdminCmd, Alias = "QUERYUSER")] + [QueryCmd("SEARCHUSER", EUserRights.AdminCmd, Alias = "QUERYUSER")] public async Task QResponseSearchUser(Users dbUser, CallbackQuery callbackQuery, string[] args) { async Task<(string, InlineKeyboardMarkup?)> exec() @@ -690,7 +684,7 @@ public async Task QResponseSearchUser(Users dbUser, CallbackQuery callbackQuery, /// /// /// - [QueryCmd("CANCELSEARCHUSER", UserRights.AdminCmd, Alias = "CANCELCLOSE")] + [QueryCmd("CANCELSEARCHUSER", EUserRights.AdminCmd, Alias = "CANCELCLOSE")] public async Task QResponseCancelSearchUser(CallbackQuery callbackQuery, string[] args) { string text = args.Length >= 2 ? args[1] : "参数有误"; @@ -702,7 +696,7 @@ public async Task QResponseCancelSearchUser(CallbackQuery callbackQuery, string[ /// /// /// - [TextCmd("POSTREPORT", UserRights.AdminCmd, Alias = "POSTSTATUS", Description = "生成投稿统计信息")] + [TextCmd("POSTREPORT", EUserRights.AdminCmd, Alias = "POSTSTATUS", Description = "生成投稿统计信息")] public async Task ResponsePostReport(Message message) { var now = DateTime.Now; @@ -714,9 +708,9 @@ public async Task ResponsePostReport(Message message) StringBuilder sb = new(); - var todayPost = await _postService.Queryable().Where(x => x.CreateAt >= prev1Day && x.Status > PostStatus.Cancel).CountAsync(); - var todayAcceptPost = await _postService.Queryable().Where(x => x.CreateAt >= prev1Day && x.Status == PostStatus.Accepted).CountAsync(); - var todayRejectPost = await _postService.Queryable().Where(x => x.CreateAt >= prev1Day && x.Status == PostStatus.Rejected).CountAsync(); + var todayPost = await _postService.Queryable().Where(x => x.CreateAt >= prev1Day && x.Status > EPostStatus.Cancel).CountAsync(); + var todayAcceptPost = await _postService.Queryable().Where(x => x.CreateAt >= prev1Day && x.Status == EPostStatus.Accepted).CountAsync(); + var todayRejectPost = await _postService.Queryable().Where(x => x.CreateAt >= prev1Day && x.Status == EPostStatus.Rejected).CountAsync(); var todayExpiredPost = await _postService.Queryable().Where(x => x.CreateAt >= prev1Day && x.Status < 0).CountAsync(); sb.AppendLine("-- 24小时投稿统计 --"); @@ -725,9 +719,9 @@ public async Task ResponsePostReport(Message message) sb.AppendLine($"过期投稿: {todayExpiredPost}"); sb.AppendLine($"累计投稿: {todayPost + todayExpiredPost}"); - var weekPost = await _postService.Queryable().Where(x => x.CreateAt >= prev7Days && x.Status > PostStatus.Cancel).CountAsync(); - var weekAcceptPost = await _postService.Queryable().Where(x => x.CreateAt >= prev7Days && x.Status == PostStatus.Accepted).CountAsync(); - var weekRejectPost = await _postService.Queryable().Where(x => x.CreateAt >= prev7Days && x.Status == PostStatus.Rejected).CountAsync(); + var weekPost = await _postService.Queryable().Where(x => x.CreateAt >= prev7Days && x.Status > EPostStatus.Cancel).CountAsync(); + var weekAcceptPost = await _postService.Queryable().Where(x => x.CreateAt >= prev7Days && x.Status == EPostStatus.Accepted).CountAsync(); + var weekRejectPost = await _postService.Queryable().Where(x => x.CreateAt >= prev7Days && x.Status == EPostStatus.Rejected).CountAsync(); var weekExpiredPost = await _postService.Queryable().Where(x => x.CreateAt >= prev7Days && x.Status < 0).CountAsync(); sb.AppendLine(); @@ -737,9 +731,9 @@ public async Task ResponsePostReport(Message message) sb.AppendLine($"过期投稿: {weekExpiredPost}"); sb.AppendLine($"累计投稿: {weekPost + weekExpiredPost}"); - var monthPost = await _postService.Queryable().Where(x => x.CreateAt >= monthStart && x.Status > PostStatus.Cancel).CountAsync(); - var monthAcceptPost = await _postService.Queryable().Where(x => x.CreateAt >= monthStart && x.Status == PostStatus.Accepted).CountAsync(); - var monthRejectPost = await _postService.Queryable().Where(x => x.CreateAt >= monthStart && x.Status == PostStatus.Rejected).CountAsync(); + var monthPost = await _postService.Queryable().Where(x => x.CreateAt >= monthStart && x.Status > EPostStatus.Cancel).CountAsync(); + var monthAcceptPost = await _postService.Queryable().Where(x => x.CreateAt >= monthStart && x.Status == EPostStatus.Accepted).CountAsync(); + var monthRejectPost = await _postService.Queryable().Where(x => x.CreateAt >= monthStart && x.Status == EPostStatus.Rejected).CountAsync(); var monthExpiredPost = await _postService.Queryable().Where(x => x.CreateAt >= monthStart && x.Status < 0).CountAsync(); sb.AppendLine(); @@ -749,9 +743,9 @@ public async Task ResponsePostReport(Message message) sb.AppendLine($"过期投稿: {monthExpiredPost}"); sb.AppendLine($"累计投稿: {monthPost}"); - var yearPost = await _postService.Queryable().Where(x => x.CreateAt >= yearStart && x.Status > PostStatus.Cancel).CountAsync(); - var yearAcceptPost = await _postService.Queryable().Where(x => x.CreateAt >= yearStart && x.Status == PostStatus.Accepted).CountAsync(); - var yearRejectPost = await _postService.Queryable().Where(x => x.CreateAt >= yearStart && x.Status == PostStatus.Rejected).CountAsync(); + var yearPost = await _postService.Queryable().Where(x => x.CreateAt >= yearStart && x.Status > EPostStatus.Cancel).CountAsync(); + var yearAcceptPost = await _postService.Queryable().Where(x => x.CreateAt >= yearStart && x.Status == EPostStatus.Accepted).CountAsync(); + var yearRejectPost = await _postService.Queryable().Where(x => x.CreateAt >= yearStart && x.Status == EPostStatus.Rejected).CountAsync(); var yearExpiredPost = await _postService.Queryable().Where(x => x.CreateAt >= yearStart && x.Status < 0).CountAsync(); sb.AppendLine(); @@ -761,9 +755,9 @@ public async Task ResponsePostReport(Message message) sb.AppendLine($"过期投稿: {yearExpiredPost}"); sb.AppendLine($"累计投稿: {yearPost}"); - var totalPost = await _postService.Queryable().Where(x => x.Status > PostStatus.Cancel).CountAsync(); - var totalAcceptPost = await _postService.Queryable().Where(x => x.Status == PostStatus.Accepted).CountAsync(); - var totalRejectPost = await _postService.Queryable().Where(x => x.Status == PostStatus.Rejected).CountAsync(); + var totalPost = await _postService.Queryable().Where(x => x.Status > EPostStatus.Cancel).CountAsync(); + var totalAcceptPost = await _postService.Queryable().Where(x => x.Status == EPostStatus.Accepted).CountAsync(); + var totalRejectPost = await _postService.Queryable().Where(x => x.Status == EPostStatus.Rejected).CountAsync(); var totalExpiredPost = await _postService.Queryable().Where(x => x.Status < 0).CountAsync(); var totalChannel = await _channelOptionService.Queryable().CountAsync(); var totalAttachment = await _attachmentService.Queryable().CountAsync(); @@ -799,7 +793,7 @@ public async Task ResponsePostReport(Message message) /// /// /// - [TextCmd("SYSREPORT", UserRights.AdminCmd, Alias = "SYSSTATUS", Description = "生成系统报表")] + [TextCmd("SYSREPORT", EUserRights.AdminCmd, Alias = "SYSSTATUS", Description = "生成系统报表")] public async Task ResponseSystemReport(Message message) { StringBuilder sb = new(); @@ -868,7 +862,7 @@ public async Task ResponseSystemReport(Message message) /// /// /// - [TextCmd("INVITE", UserRights.AdminCmd, Description = "创建审核群的邀请链接")] + [TextCmd("INVITE", EUserRights.AdminCmd, Description = "创建审核群的邀请链接")] public async Task ResponseInviteToReviewGroup(Users dbUser, Message message) { if (_channelService.ReviewGroup.Id == -1) @@ -907,7 +901,7 @@ public async Task ResponseInviteToReviewGroup(Users dbUser, Message message) /// /// /// - [TextCmd("USERRANK", UserRights.AdminCmd, Alias = "URANK", Description = "查看用户排行榜")] + [TextCmd("USERRANK", EUserRights.AdminCmd, Alias = "URANK", Description = "查看用户排行榜")] public async Task ResponseUserRank(Message message) { var now = DateTime.Now; @@ -978,7 +972,7 @@ public async Task ResponseUserRank(Message message) /// /// /// - [TextCmd("SETUSERGROUP", UserRights.AdminCmd, Alias = "SUGROUP", Description = "设置用户组")] + [TextCmd("SETUSERGROUP", EUserRights.AdminCmd, Alias = "SUGROUP", Description = "设置用户组")] public async Task SetUserGroup(Users dbUser, Message message, string[] args) { async Task<(string, InlineKeyboardMarkup?)> exec() @@ -1028,7 +1022,7 @@ public async Task SetUserGroup(Users dbUser, Message message, string[] args) /// /// /// - [QueryCmd("SETUSERGROUP", UserRights.AdminCmd)] + [QueryCmd("SETUSERGROUP", EUserRights.AdminCmd)] public async Task QResponseSetUserGroup(Users dbUser, CallbackQuery callbackQuery, string[] args) { async Task exec() @@ -1092,7 +1086,7 @@ async Task exec() /// /// /// - [TextCmd("MESSAGE", UserRights.AdminCmd, Alias = "MSG", Description = "查看消息详情")] + [TextCmd("MESSAGE", EUserRights.AdminCmd, Alias = "MSG", Description = "查看消息详情")] public async Task GetMessageDetail(Message message) { var msg = message.ReplyToMessage ?? message; @@ -1144,7 +1138,7 @@ public async Task GetMessageDetail(Message message) /// /// /// - [TextCmd("NUKE", UserRights.AdminCmd, Alias = "SB,SUPERBAN", Description = "联BAN用户")] + [TextCmd("NUKE", EUserRights.AdminCmd, Alias = "SB,SUPERBAN", Description = "联BAN用户")] public async Task ResponseNuke(Users dbUser, Message message, string[] args) { async Task<(InlineKeyboardMarkup?, string)> exec() @@ -1182,17 +1176,17 @@ public async Task ResponseNuke(Users dbUser, Message message, string[] args) } //获取最近一条解封记录 - var lastUnbaned = await _banRecordService.Queryable().Where(x => x.UserID == targetUser.UserID && (x.Type == BanType.UnBan || x.Type == BanType.Ban)) + var lastUnbaned = await _banRecordService.Queryable().Where(x => x.UserID == targetUser.UserID && (x.Type == EBanType.UnBan || x.Type == EBanType.Ban)) .OrderByDescending(x => x.BanTime).FirstAsync(); int warnCount; if (lastUnbaned == null) { - warnCount = await _banRecordService.Queryable().Where(x => x.UserID == targetUser.UserID && x.Type == BanType.Warning).CountAsync(); + warnCount = await _banRecordService.Queryable().Where(x => x.UserID == targetUser.UserID && x.Type == EBanType.Warning).CountAsync(); } else { - warnCount = await _banRecordService.Queryable().Where(x => x.UserID == targetUser.UserID && x.Type == BanType.Warning && x.BanTime >= lastUnbaned.BanTime).CountAsync(); + warnCount = await _banRecordService.Queryable().Where(x => x.UserID == targetUser.UserID && x.Type == EBanType.Warning && x.BanTime >= lastUnbaned.BanTime).CountAsync(); } StringBuilder sb = new(); @@ -1217,7 +1211,7 @@ public async Task ResponseNuke(Users dbUser, Message message, string[] args) /// /// /// - [QueryCmd("NUKE", UserRights.AdminCmd, Description = "联BAN用户")] + [QueryCmd("NUKE", EUserRights.AdminCmd, Description = "联BAN用户")] public async Task QResponseNuke(Users dbUser, CallbackQuery callbackQuery, string[] args) { if (args.Length < 4) @@ -1247,8 +1241,9 @@ public async Task QResponseNuke(Users dbUser, CallbackQuery callbackQuery, strin { await _botClient.RestrictChatMemberAsync(_channelService.SubGroup, targetUser.UserID, permission); } - catch { - + catch + { + } await _botClient.RestrictChatMemberAsync(_channelService.SubGroup, targetUser.UserID, permission); } @@ -1274,28 +1269,25 @@ public async Task QResponseNuke(Users dbUser, CallbackQuery callbackQuery, strin return; } - string action = args[1] switch - { + string action = args[1] switch { "mute" => "全局禁言", "ban" => "全局封禁", "unmute" => "撤销全局禁言", "unban" => "撤销全局封禁", _ => "未知", }; - BanType banType = args[1] switch - { - "mute" => BanType.GlobalMute, - "ban" => BanType.GlobalBan, - "unmute" => BanType.GlobalUnMute, - "unban" => BanType.GlobalUnBan, - _ => BanType.GlobalMute, + EBanType banType = args[1] switch { + "mute" => EBanType.GlobalMute, + "ban" => EBanType.GlobalBan, + "unmute" => EBanType.GlobalUnMute, + "unban" => EBanType.GlobalUnBan, + _ => EBanType.GlobalMute, }; string reason = string.Join(' ', args[3..]); - var record = new BanRecords - { + var record = new BanRecords { UserID = targetUser.UserID, OperatorUID = dbUser.UserID, Type = banType, @@ -1333,12 +1325,12 @@ public async Task QResponseNuke(Users dbUser, CallbackQuery callbackQuery, strin /// /// /// - [QueryCmd("REPOST", UserRights.AdminCmd)] - public async Task QResponseRepost(Users dbUser, CallbackQuery callbackQuery, string[] args) - { - //TODO - _logger.LogInformation(args.ToString()); - } + //[QueryCmd("REPOST", UserRights.AdminCmd)] + //public async Task QResponseRepost(Users dbUser, CallbackQuery callbackQuery, string[] args) + //{ + // //TODO + // _logger.LogInformation(args.ToString()); + //} } diff --git a/XinjingdailyBot.Command/CommonCommand.cs b/XinjingdailyBot.Command/CommonCommand.cs index 48bca210..93b7595e 100644 --- a/XinjingdailyBot.Command/CommonCommand.cs +++ b/XinjingdailyBot.Command/CommonCommand.cs @@ -1,5 +1,5 @@ -using System.Text; -using Microsoft.Extensions.Options; +using Microsoft.Extensions.Options; +using System.Text; using Telegram.Bot; using Telegram.Bot.Types; using Telegram.Bot.Types.Enums; @@ -43,7 +43,7 @@ public CommonCommand( /// /// /// - [TextCmd("HELP", UserRights.None, Description = "显示命令帮助")] + [TextCmd("HELP", EUserRights.None, Description = "显示命令帮助")] public async Task ResponseHelp(Users dbUser, Message message) { StringBuilder sb = new(); @@ -68,7 +68,7 @@ public async Task ResponseHelp(Users dbUser, Message message) /// /// /// - [TextCmd("START", UserRights.None, Description = "首次欢迎语")] + [TextCmd("START", EUserRights.None, Description = "首次欢迎语")] public async Task ResponseStart(Users dbUser, Message message) { StringBuilder sb = new(); @@ -97,7 +97,7 @@ public async Task ResponseStart(Users dbUser, Message message) /// /// /// - [TextCmd("ABOUT", UserRights.None, Description = "关于机器人")] + [TextCmd("ABOUT", EUserRights.None, Description = "关于机器人")] public async Task ResponseAbout(Message message) { StringBuilder sb = new(); @@ -115,7 +115,7 @@ public async Task ResponseAbout(Message message) /// /// /// - [TextCmd("VERSION", UserRights.None, Description = "查看机器人版本")] + [TextCmd("VERSION", EUserRights.None, Description = "查看机器人版本")] public async Task ResponseVersion(Message message) { StringBuilder sb = new(); @@ -134,7 +134,7 @@ public async Task ResponseVersion(Message message) /// /// /// - [TextCmd("MYBAN", UserRights.None, Description = "查询自己是否被封禁")] + [TextCmd("MYBAN", EUserRights.None, Description = "查询自己是否被封禁")] public async Task ResponseMyBan(Users dbUser, Message message) { var records = await _banRecordService.Queryable().Where(x => x.UserID == dbUser.UserID) @@ -161,11 +161,10 @@ public async Task ResponseMyBan(Users dbUser, Message message) foreach (var record in records) { string date = record.BanTime.ToString("d"); - string operate = record.Type switch - { - BanType.UnBan => "解封", - BanType.Ban => "封禁", - BanType.Warning => "警告", + string operate = record.Type switch { + EBanType.UnBan => "解封", + EBanType.Ban => "封禁", + EBanType.Warning => "警告", _ => "其他", }; sb.AppendLine($"在 {date} 因为 {record.Reason} 被 {operate}"); diff --git a/XinjingdailyBot.Command/NormalCommand.cs b/XinjingdailyBot.Command/NormalCommand.cs index abd1b8f5..914e5111 100644 --- a/XinjingdailyBot.Command/NormalCommand.cs +++ b/XinjingdailyBot.Command/NormalCommand.cs @@ -1,6 +1,6 @@ -using System.Net; +using SqlSugar; +using System.Net; using System.Text; -using SqlSugar; using Telegram.Bot; using Telegram.Bot.Types; using Telegram.Bot.Types.Enums; @@ -54,7 +54,7 @@ public NormalCommand( /// /// /// - [TextCmd("PING", UserRights.NormalCmd, Description = "检测机器人是否存活")] + [TextCmd("PING", EUserRights.NormalCmd, Description = "检测机器人是否存活")] public async Task ResponsePing(Message message) { await _botClient.SendCommandReply("PONG!", message); @@ -66,7 +66,7 @@ public async Task ResponsePing(Message message) /// /// /// - [TextCmd("ANONYMOUS", UserRights.NormalCmd, Alias = "ANYMOUSE", Description = "设置是否匿名")] + [TextCmd("ANONYMOUS", EUserRights.NormalCmd, Alias = "ANYMOUSE", Description = "设置是否匿名")] public async Task ResponseAnonymous(Users dbUser, Message message) { if (message.Chat.Type != ChatType.Private) @@ -91,7 +91,7 @@ public async Task ResponseAnonymous(Users dbUser, Message message) /// /// /// - [TextCmd("NOTIFICATION", UserRights.NormalCmd, Description = "设置稿件审核后是否通知")] + [TextCmd("NOTIFICATION", EUserRights.NormalCmd, Description = "设置稿件审核后是否通知")] public async Task ResponseNotification(Users dbUser, Message message) { if (message.Chat.Type != ChatType.Private) @@ -116,7 +116,7 @@ public async Task ResponseNotification(Users dbUser, Message message) /// /// /// - [TextCmd("MYINFO", UserRights.NormalCmd, Description = "获取自己的信息")] + [TextCmd("MYINFO", EUserRights.NormalCmd, Description = "获取自己的信息")] public async Task ResponseMyInfo(Users dbUser, Message message) { StringBuilder sb = new(); @@ -138,16 +138,16 @@ public async Task ResponseMyInfo(Users dbUser, Message message) /// /// /// - [TextCmd("MYRIGHT", UserRights.NormalCmd, Description = "获取自己的权限")] + [TextCmd("MYRIGHT", EUserRights.NormalCmd, Description = "获取自己的权限")] public async Task ResponseMyRight(Users dbUser, Message message) { var right = dbUser.Right; - bool superCmd = right.HasFlag(UserRights.SuperCmd); - bool adminCmd = right.HasFlag(UserRights.AdminCmd); - bool normalCmd = right.HasFlag(UserRights.NormalCmd); - bool sendPost = right.HasFlag(UserRights.SendPost); - bool reviewPost = right.HasFlag(UserRights.ReviewPost); - bool directPost = right.HasFlag(UserRights.DirectPost); + bool superCmd = right.HasFlag(EUserRights.SuperCmd); + bool adminCmd = right.HasFlag(EUserRights.AdminCmd); + bool normalCmd = right.HasFlag(EUserRights.NormalCmd); + bool sendPost = right.HasFlag(EUserRights.SendPost); + bool reviewPost = right.HasFlag(EUserRights.ReviewPost); + bool directPost = right.HasFlag(EUserRights.DirectPost); string userNick = message.From!.EscapedNickName(); string group = _groupRepository.GetGroupName(dbUser.GroupID); @@ -178,7 +178,7 @@ public async Task ResponseMyRight(Users dbUser, Message message) /// /// /// - [TextCmd("ADMIN", UserRights.NormalCmd, Description = "艾特群管理")] + [TextCmd("ADMIN", EUserRights.NormalCmd, Description = "艾特群管理")] public async Task ResponseCallAdmins(Message message) { StringBuilder sb = new(); @@ -210,7 +210,7 @@ public async Task ResponseCallAdmins(Message message) /// /// /// - [QueryCmd("CANCEL", UserRights.NormalCmd, Alias = "CANCELCLOSE CANCELANDCLOSE")] + [QueryCmd("CANCEL", EUserRights.NormalCmd, Alias = "CANCELCLOSE CANCELANDCLOSE")] public async Task QResponseCancel(CallbackQuery query, string[] args) { string text = args.Length > 1 ? string.Join(' ', args[1..]) : "操作已取消"; @@ -225,7 +225,7 @@ public async Task QResponseCancel(CallbackQuery query, string[] args) /// /// /// - [QueryCmd("SAY", UserRights.NormalCmd)] + [QueryCmd("SAY", EUserRights.NormalCmd)] public async Task QResponseSay(CallbackQuery query, string[] args) { string text; @@ -246,10 +246,10 @@ public async Task QResponseSay(CallbackQuery query, string[] args) /// /// /// - [TextCmd("RANDOMPOST", UserRights.NormalCmd, Description = "获取随机稿件")] + [TextCmd("RANDOMPOST", EUserRights.NormalCmd, Description = "获取随机稿件")] public async Task ResponseRandomPost(Users dbUser, Message message) { - if (!dbUser.Right.HasFlag(UserRights.AdminCmd)) + if (!dbUser.Right.HasFlag(EUserRights.AdminCmd)) { if (message.Chat.Type != ChatType.Private) { @@ -268,7 +268,7 @@ public async Task ResponseRandomPost(Users dbUser, Message message) /// /// /// - [QueryCmd("SETRANDOMPOST", UserRights.NormalCmd)] + [QueryCmd("SETRANDOMPOST", EUserRights.NormalCmd)] public async Task QResponseSetRandomPost(Users dbUser, CallbackQuery callbackQuery, string[] args) { if (args.Length < 1) @@ -301,7 +301,7 @@ public async Task QResponseSetRandomPost(Users dbUser, CallbackQuery callbackQue /// /// /// - [QueryCmd("BACKRANDOMPOST", UserRights.NormalCmd)] + [QueryCmd("BACKRANDOMPOST", EUserRights.NormalCmd)] public async Task QResponseBackRandomPost(Users dbUser, CallbackQuery callbackQuery) { var keyboard = _markupHelperService.RandomPostMenuKeyboard(dbUser); @@ -315,7 +315,7 @@ public async Task QResponseBackRandomPost(Users dbUser, CallbackQuery callbackQu /// /// /// - [QueryCmd("RANDOMPOST", UserRights.NormalCmd)] + [QueryCmd("RANDOMPOST", EUserRights.NormalCmd)] public async Task QGetRandomPost(Users dbUser, CallbackQuery callbackQuery, string[] args) { if (args.Length < 3 || !int.TryParse(args[1], out int tagId)) @@ -324,8 +324,7 @@ public async Task QGetRandomPost(Users dbUser, CallbackQuery callbackQuery, stri return; } - MessageType? postType = args[2] switch - { + MessageType? postType = args[2] switch { "photo" => MessageType.Photo, "video" => MessageType.Video, "audio" => MessageType.Audio, @@ -338,10 +337,10 @@ public async Task QGetRandomPost(Users dbUser, CallbackQuery callbackQuery, stri var tag = tagId != 0 ? _tagRepository.GetTagById(tagId) : null; var randomPost = await _postService.Queryable() - .Where(x => x.Status == PostStatus.Accepted) + .Where(x => x.Status == EPostStatus.Accepted) .WhereIF(postType == null, x => x.PostType != MessageType.Text) .WhereIF(postType != null, x => x.PostType == postType) - .WhereIF(tag != null, x => (x.NewTags & tag!.Seg) > 0) + .WhereIF(tag != null, x => (x.Tags & tag!.Seg) > 0) .OrderBy(x => SqlFunc.GetRandom()).FirstAsync(); if (randomPost != null) @@ -361,8 +360,7 @@ public async Task QGetRandomPost(Users dbUser, CallbackQuery callbackQuery, stri { attachmentType = randomPost.PostType; } - group[i] = attachmentType switch - { + group[i] = attachmentType switch { MessageType.Photo => new InputMediaPhoto(new InputFileId(attachments[i].FileID)) { Caption = i == 0 ? randomPost.Text : null, ParseMode = ParseMode.Html, HasSpoiler = hasSpoiler }, MessageType.Audio => new InputMediaAudio(new InputFileId(attachments[i].FileID)) { Caption = i == 0 ? randomPost.Text : null, ParseMode = ParseMode.Html }, MessageType.Video => new InputMediaVideo(new InputFileId(attachments[i].FileID)) { Caption = i == 0 ? randomPost.Text : null, ParseMode = ParseMode.Html, HasSpoiler = hasSpoiler }, @@ -381,8 +379,7 @@ public async Task QGetRandomPost(Users dbUser, CallbackQuery callbackQuery, stri else { Attachments attachment = await _attachmentService.Queryable().FirstAsync(x => x.PostID == randomPost.Id); - var handler = randomPost.PostType switch - { + var handler = randomPost.PostType switch { MessageType.Text => _botClient.SendTextMessageAsync(chat, randomPost.Text), MessageType.Photo => _botClient.SendPhotoAsync(chat, new InputFileId(attachment.FileID), caption: randomPost.Text, parseMode: ParseMode.Html, replyMarkup: keyboard, hasSpoiler: hasSpoiler), MessageType.Audio => _botClient.SendAudioAsync(chat, new InputFileId(attachment.FileID), caption: randomPost.Text, parseMode: ParseMode.Html, replyMarkup: keyboard, title: attachment.FileName), @@ -420,7 +417,7 @@ public async Task QGetRandomPost(Users dbUser, CallbackQuery callbackQuery, stri } } - [TextCmd("IP", UserRights.NormalCmd, Alias = "IPINFO", Description = "查询IP信息")] + [TextCmd("IP", EUserRights.NormalCmd, Alias = "IPINFO", Description = "查询IP信息")] public async Task GetIpInfo(Message message, string[] args) { StringBuilder sb = new(); diff --git a/XinjingdailyBot.Command/PostCommand.cs b/XinjingdailyBot.Command/PostCommand.cs index 25315e90..a204d552 100644 --- a/XinjingdailyBot.Command/PostCommand.cs +++ b/XinjingdailyBot.Command/PostCommand.cs @@ -49,11 +49,11 @@ public PostCommand( /// /// /// - [QueryCmd("POST", UserRights.SendPost, Description = "投稿消息处理")] + [QueryCmd("POST", EUserRights.SendPost, Description = "投稿消息处理")] public async Task HandlePostQuery(Users dbUser, CallbackQuery query) { var message = query.Message!; - var post = await _postService.FetchPostFromConfirmCallbackQuery(query); + var post = await _postService.FetchPostFromCallbackQuery(query); if (post == null) { @@ -62,7 +62,7 @@ public async Task HandlePostQuery(Users dbUser, CallbackQuery query) return; } - if (post.Status != PostStatus.Padding) + if (post.Status != EPostStatus.Padding) { await _botClient.AutoReplyAsync("请不要重复操作", query); await _botClient.EditMessageReplyMarkupAsync(message, null); @@ -97,7 +97,7 @@ public async Task HandlePostQuery(Users dbUser, CallbackQuery query) /// /// /// - private async Task SetAnymouse(Posts post, CallbackQuery query) + private async Task SetAnymouse(NewPosts post, CallbackQuery query) { await _botClient.AutoReplyAsync("可以使用命令 /anymouse 切换默认匿名投稿", query); @@ -116,9 +116,9 @@ private async Task SetAnymouse(Posts post, CallbackQuery query) /// /// /// - private async Task CancelPost(Posts post, CallbackQuery query) + private async Task CancelPost(NewPosts post, CallbackQuery query) { - post.Status = PostStatus.Cancel; + post.Status = EPostStatus.Cancel; post.ModifyAt = DateTime.Now; await _postService.Updateable(post).UpdateColumns(x => new { x.Status, x.ModifyAt }).ExecuteCommandAsync(); @@ -133,7 +133,7 @@ private async Task CancelPost(Posts post, CallbackQuery query) /// /// /// - private async Task ConfirmPost(Posts post, Users dbUser, CallbackQuery query) + private async Task ConfirmPost(NewPosts post, Users dbUser, CallbackQuery query) { if (await _postService.CheckPostLimit(dbUser, null, query) == false) { @@ -157,8 +157,7 @@ private async Task ConfirmPost(Posts post, Users dbUser, CallbackQuery query) attachmentType = post.PostType; } - group[i] = attachmentType switch - { + group[i] = attachmentType switch { MessageType.Photo => new InputMediaPhoto(new InputFileId(attachments[i].FileID)) { Caption = i == 0 ? post.Text : null, ParseMode = ParseMode.Html }, MessageType.Audio => new InputMediaAudio(new InputFileId(attachments[i].FileID)) { Caption = i == 0 ? post.Text : null, ParseMode = ParseMode.Html }, MessageType.Video => new InputMediaVideo(new InputFileId(attachments[i].FileID)) { Caption = i == 0 ? post.Text : null, ParseMode = ParseMode.Html }, @@ -168,6 +167,7 @@ private async Task ConfirmPost(Posts post, Users dbUser, CallbackQuery query) } var messages = await _botClient.SendMediaGroupAsync(_channelService.ReviewGroup.Id, group); reviewMsg = messages.First(); + post.ReviewMediaGroupID = reviewMsg.MediaGroupId ?? ""; //记录媒体组消息 await _mediaGroupService.AddPostMediaGroup(messages); @@ -176,15 +176,25 @@ private async Task ConfirmPost(Posts post, Users dbUser, CallbackQuery query) string msg = _textHelperService.MakeReviewMessage(dbUser, post.Anonymous); bool? hasSpoiler = post.CanSpoiler ? post.HasSpoiler : null; - var keyboard = _markupHelperService.ReviewKeyboardA(post.NewTags, hasSpoiler); + var keyboard = _markupHelperService.ReviewKeyboardA(post.Tags, hasSpoiler); Message manageMsg = await _botClient.SendTextMessageAsync(_channelService.ReviewGroup.Id, msg, parseMode: ParseMode.Html, disableWebPagePreview: true, replyToMessageId: reviewMsg.MessageId, replyMarkup: keyboard, allowSendingWithoutReply: true); + post.ReviewChatID = reviewMsg.Chat.Id; post.ReviewMsgID = reviewMsg.MessageId; - post.ManageMsgID = manageMsg.MessageId; - post.Status = PostStatus.Reviewing; + post.ReviewActionChatID = manageMsg.MessageId; + post.ReviewActionMsgID = manageMsg.MessageId; + post.Status = EPostStatus.Reviewing; post.ModifyAt = DateTime.Now; - await _postService.Updateable(post).UpdateColumns(x => new { x.ReviewMsgID, x.ManageMsgID, x.Status, x.ModifyAt }).ExecuteCommandAsync(); + await _postService.Updateable(post).UpdateColumns(x => new { + x.ReviewChatID, + x.ReviewMsgID, + x.ReviewActionChatID, + x.ReviewActionMsgID, + x.ReviewMediaGroupID, + x.Status, + x.ModifyAt + }).ExecuteCommandAsync(); await _botClient.AutoReplyAsync(Langs.PostSendSuccess, query); await _botClient.EditMessageTextAsync(query.Message!, Langs.ThanksForSendingPost, replyMarkup: null); diff --git a/XinjingdailyBot.Command/ReviewCommand.cs b/XinjingdailyBot.Command/ReviewCommand.cs index d007d956..64ccd253 100644 --- a/XinjingdailyBot.Command/ReviewCommand.cs +++ b/XinjingdailyBot.Command/ReviewCommand.cs @@ -9,6 +9,7 @@ using XinjingdailyBot.Interface.Data; using XinjingdailyBot.Interface.Helper; using XinjingdailyBot.Model.Models; +using XinjingdailyBot.Repository; namespace XinjingdailyBot.Command { @@ -19,23 +20,23 @@ public class ReviewCommand private readonly IUserService _userService; private readonly IChannelService _channelService; private readonly IPostService _postService; - private readonly ITextHelperService _textHelperService; private readonly IMarkupHelperService _markupHelperService; + private readonly RejectReasonRepository _rejectReasonRepository; public ReviewCommand( ITelegramBotClient botClient, IUserService userService, IChannelService channelService, IPostService postService, - ITextHelperService textHelperService, - IMarkupHelperService markupHelperService) + IMarkupHelperService markupHelperService, + RejectReasonRepository rejectReasonRepository) { _botClient = botClient; _userService = userService; _channelService = channelService; _postService = postService; - _textHelperService = textHelperService; _markupHelperService = markupHelperService; + _rejectReasonRepository = rejectReasonRepository; } /// @@ -45,7 +46,7 @@ public ReviewCommand( /// /// /// - [TextCmd("NO", UserRights.ReviewPost, Description = "自定义拒绝稿件理由")] + [TextCmd("NO", EUserRights.ReviewPost, Description = "自定义拒绝稿件理由")] public async Task ResponseNo(Users dbUser, Message message, string[] args) { async Task exec() @@ -66,7 +67,7 @@ async Task exec() return "未找到稿件"; } - if (post.Status != PostStatus.Reviewing) + if (post.Status != EPostStatus.Reviewing) { return "仅能编辑状态为审核中的稿件"; } @@ -78,8 +79,12 @@ async Task exec() return "请输入拒绝理由"; } - post.Reason = RejectReason.CustomReason; - await _postService.RejetPost(post, dbUser, reason); + post.RejectReason = reason; + var rejectReason = new RejectReasons { + Name = reason, + FullText = reason, + }; + await _postService.RejetPost(post, dbUser, rejectReason); return $"已拒绝该稿件, 理由: {reason}"; } @@ -95,7 +100,7 @@ async Task exec() /// /// /// - [TextCmd("EDIT", UserRights.ReviewPost, Description = "修改稿件文字说明")] + [TextCmd("EDIT", EUserRights.ReviewPost, Description = "修改稿件文字说明")] public async Task ResponseEditPost(Users dbUser, Message message, string[] args) { async Task exec() @@ -116,7 +121,7 @@ async Task exec() return "未找到稿件"; } - if (post.Status != PostStatus.Reviewing) + if (post.Status != EPostStatus.Reviewing) { return "仅能编辑状态为审核中的稿件"; } @@ -143,11 +148,11 @@ async Task exec() /// /// /// - [QueryCmd("REVIEW", UserRights.ReviewPost, Alias = "REJECT", Description = "审核稿件")] + [QueryCmd("REVIEW", EUserRights.ReviewPost, Alias = "REJECT", Description = "审核稿件")] public async Task HandleQuery(Users dbUser, CallbackQuery callbackQuery) { var message = callbackQuery.Message!; - var post = await _postService.FetchPostFromReviewCallbackQuery(callbackQuery); + var post = await _postService.FetchPostFromCallbackQuery(callbackQuery); if (post == null) { await _botClient.AutoReplyAsync("未找到稿件", callbackQuery, true); @@ -155,14 +160,14 @@ public async Task HandleQuery(Users dbUser, CallbackQuery callbackQuery) return; } - if (post.Status != PostStatus.Reviewing) + if (post.Status != EPostStatus.Reviewing) { await _botClient.AutoReplyAsync("请不要重复操作", callbackQuery, true); await _botClient.EditMessageReplyMarkupAsync(message, null); return; } - if (!dbUser.Right.HasFlag(UserRights.ReviewPost)) + if (!dbUser.Right.HasFlag(EUserRights.ReviewPost)) { await _botClient.AutoReplyAsync("无权操作", callbackQuery, true); return; @@ -180,7 +185,10 @@ public async Task HandleQuery(Users dbUser, CallbackQuery callbackQuery) case "review reject": await SwitchKeyboard(true, post, callbackQuery); break; + + //兼容旧的callback data case "reject back": + case "review reject back": await SwitchKeyboard(false, post, callbackQuery); break; @@ -188,28 +196,6 @@ public async Task HandleQuery(Users dbUser, CallbackQuery callbackQuery) await SetSpoiler(post, callbackQuery); break; - case "reject fuzzy": - await RejectPostHelper(post, dbUser, RejectReason.Fuzzy); - break; - case "reject duplicate": - await RejectPostHelper(post, dbUser, RejectReason.Duplicate); - break; - case "reject boring": - await RejectPostHelper(post, dbUser, RejectReason.Boring); - break; - case "reject confusing": - await RejectPostHelper(post, dbUser, RejectReason.Confused); - break; - case "reject deny": - await RejectPostHelper(post, dbUser, RejectReason.Deny); - break; - case "reject qrcode": - await RejectPostHelper(post, dbUser, RejectReason.QRCode); - break; - case "reject other": - await RejectPostHelper(post, dbUser, RejectReason.Other); - break; - case "review accept": await _postService.AcceptPost(post, dbUser, callbackQuery); break; @@ -235,6 +221,11 @@ public async Task HandleQuery(Users dbUser, CallbackQuery callbackQuery) await SetSpoiler(post, callbackQuery); } } + else if (data.StartsWith("reject ")) + { + var payload = data[7..]; + await RejectPostHelper(post, dbUser, callbackQuery, payload); + } break; } @@ -246,7 +237,7 @@ public async Task HandleQuery(Users dbUser, CallbackQuery callbackQuery) /// /// /// - private async Task SetAnymouse(Posts post, CallbackQuery query) + private async Task SetAnymouse(NewPosts post, CallbackQuery query) { await _botClient.AutoReplyAsync("可以使用命令 /anymouse 切换默认匿名投稿", query); @@ -257,7 +248,7 @@ private async Task SetAnymouse(Posts post, CallbackQuery query) bool? hasSpoiler = post.CanSpoiler ? post.HasSpoiler : null; - var keyboard = _markupHelperService.DirectPostKeyboard(anonymous, post.NewTags, hasSpoiler); + var keyboard = _markupHelperService.DirectPostKeyboard(anonymous, post.Tags, hasSpoiler); await _botClient.EditMessageReplyMarkupAsync(query.Message!, keyboard); } @@ -267,7 +258,7 @@ private async Task SetAnymouse(Posts post, CallbackQuery query) /// /// /// - private async Task SetSpoiler(Posts post, CallbackQuery query) + private async Task SetSpoiler(NewPosts post, CallbackQuery query) { if (!post.CanSpoiler) { @@ -282,8 +273,8 @@ private async Task SetSpoiler(Posts post, CallbackQuery query) await _botClient.AutoReplyAsync(post.HasSpoiler ? "启用遮罩" : "禁用遮罩", query); var keyboard = post.IsDirectPost ? - _markupHelperService.DirectPostKeyboard(post.Anonymous, post.NewTags, post.HasSpoiler) : - _markupHelperService.ReviewKeyboardA(post.NewTags, post.HasSpoiler); + _markupHelperService.DirectPostKeyboard(post.Anonymous, post.Tags, post.HasSpoiler) : + _markupHelperService.ReviewKeyboardA(post.Tags, post.HasSpoiler); await _botClient.EditMessageReplyMarkupAsync(query.Message!, keyboard); } @@ -293,9 +284,9 @@ private async Task SetSpoiler(Posts post, CallbackQuery query) /// /// /// - private async Task CancelPost(Posts post, CallbackQuery query) + private async Task CancelPost(NewPosts post, CallbackQuery query) { - post.Status = PostStatus.Cancel; + post.Status = EPostStatus.Cancel; post.ModifyAt = DateTime.Now; await _postService.Updateable(post).UpdateColumns(x => new { x.Status, x.ModifyAt }).ExecuteCommandAsync(); @@ -309,12 +300,17 @@ private async Task CancelPost(Posts post, CallbackQuery query) /// /// /// - /// + /// + /// /// - private async Task RejectPostHelper(Posts post, Users dbUser, RejectReason rejectReason) + private async Task RejectPostHelper(NewPosts post, Users dbUser, CallbackQuery query, string payload) { - post.Reason = rejectReason; - string reason = _textHelperService.RejectReasonToString(rejectReason); + var reason = _rejectReasonRepository.GetReasonByPayload(payload); + if (reason == null) + { + await _botClient.AutoReplyAsync($"找不到 {payload} 对应的拒绝理由", query, true); + return; + } await _postService.RejetPost(post, dbUser, reason); } @@ -322,9 +318,10 @@ private async Task RejectPostHelper(Posts post, Users dbUser, RejectReason rejec /// 设置inlineKeyboard /// /// + /// /// /// - private async Task SwitchKeyboard(bool rejectMode, Posts post, CallbackQuery callbackQuery) + private async Task SwitchKeyboard(bool rejectMode, NewPosts post, CallbackQuery callbackQuery) { if (rejectMode) { @@ -335,7 +332,7 @@ private async Task SwitchKeyboard(bool rejectMode, Posts post, CallbackQuery cal var keyboard = rejectMode ? _markupHelperService.ReviewKeyboardB() : - _markupHelperService.ReviewKeyboardA(post.NewTags, hasSpoiler); + _markupHelperService.ReviewKeyboardA(post.Tags, hasSpoiler); await _botClient.EditMessageReplyMarkupAsync(callbackQuery.Message!, keyboard); } diff --git a/XinjingdailyBot.Command/SuperCommand.cs b/XinjingdailyBot.Command/SuperCommand.cs index 671e3d1d..37014c6a 100644 --- a/XinjingdailyBot.Command/SuperCommand.cs +++ b/XinjingdailyBot.Command/SuperCommand.cs @@ -1,7 +1,7 @@ -using System.Diagnostics; +using Microsoft.Extensions.Logging; +using System.Diagnostics; using System.IO.Compression; using System.Text; -using Microsoft.Extensions.Logging; using Telegram.Bot; using Telegram.Bot.Types; using Telegram.Bot.Types.Enums; @@ -15,6 +15,7 @@ using XinjingdailyBot.Interface.Data; using XinjingdailyBot.Interface.Helper; using XinjingdailyBot.Model.Models; +using XinjingdailyBot.Repository; namespace XinjingdailyBot.Command { @@ -24,6 +25,8 @@ public class SuperCommand private readonly ILogger _logger; private readonly ITelegramBotClient _botClient; private readonly IPostService _postService; + [Obsolete("迁移使用")] + private readonly OldPostRepository _oldPostService; private readonly IChannelOptionService _channelOptionService; private readonly IChannelService _channelService; private readonly IMarkupHelperService _markupHelperService; @@ -32,10 +35,12 @@ public class SuperCommand private readonly IHttpHelperService _httpHelperService; private readonly ITextHelperService _textHelperService; + [Obsolete("迁移使用")] public SuperCommand( ILogger logger, ITelegramBotClient botClient, IPostService postService, + OldPostRepository oldPostService, IChannelOptionService channelOptionService, IChannelService channelService, IMarkupHelperService markupHelperService, @@ -47,6 +52,7 @@ public SuperCommand( _logger = logger; _botClient = botClient; _postService = postService; + _oldPostService = oldPostService; _channelOptionService = channelOptionService; _channelService = channelService; _markupHelperService = markupHelperService; @@ -61,7 +67,7 @@ public SuperCommand( /// /// /// - [TextCmd("RESTART", UserRights.SuperCmd, Description = "重启机器人")] + [TextCmd("RESTART", EUserRights.SuperCmd, Description = "重启机器人")] public async Task ResponseRestart(Message message) { try @@ -84,7 +90,7 @@ public async Task ResponseRestart(Message message) /// /// /// - [TextCmd("EXIT", UserRights.SuperCmd, Description = "终止机器人")] + [TextCmd("EXIT", EUserRights.SuperCmd, Description = "终止机器人")] public async Task ResponseExit(Message message) { await _botClient.SendCommandReply("机器人即将退出", message); @@ -97,7 +103,7 @@ public async Task ResponseExit(Message message) /// /// /// - [TextCmd("CHANNELOPTION", UserRights.SuperCmd, Description = "来源频道设置")] + [TextCmd("CHANNELOPTION", EUserRights.SuperCmd, Description = "来源频道设置")] public async Task ResponseChannalOption(Users dbUser, Message message) { async Task<(string, InlineKeyboardMarkup?)> exec() @@ -124,18 +130,17 @@ public async Task ResponseChannalOption(Users dbUser, Message message) return ("不是来自其他频道的投稿, 无法设置频道选项", null); } - var channel = await _channelOptionService.FetchChannelByTitle(post.ChannelTitle); + var channel = await _channelOptionService.Queryable().FirstAsync(x => x.ChannelID == post.ChannelID); if (channel == null) { return ("未找到对应频道", null); } - string option = channel.Option switch - { - ChannelOption.Normal => "1. 不做特殊处理", - ChannelOption.PurgeOrigin => "2. 抹除频道来源", - ChannelOption.AutoReject => "3. 拒绝此频道的投稿", + string option = channel.Option switch { + EChannelOption.Normal => "1. 不做特殊处理", + EChannelOption.PurgeOrigin => "2. 抹除频道来源", + EChannelOption.AutoReject => "3. 拒绝此频道的投稿", _ => "未知的值", }; @@ -154,7 +159,7 @@ public async Task ResponseChannalOption(Users dbUser, Message message) /// /// /// - [QueryCmd("CHANNELOPTION", UserRights.SuperCmd, Description = "来源频道设置")] + [QueryCmd("CHANNELOPTION", EUserRights.SuperCmd, Description = "来源频道设置")] public async Task QResponseChannalOption(CallbackQuery query, string[] args) { async Task exec() @@ -169,19 +174,17 @@ async Task exec() return "参数有误"; } - ChannelOption? option = args[2] switch - { - "normal" => ChannelOption.Normal, - "purgeorigin" => ChannelOption.PurgeOrigin, - "autoreject" => ChannelOption.AutoReject, + EChannelOption? option = args[2] switch { + "normal" => EChannelOption.Normal, + "purgeorigin" => EChannelOption.PurgeOrigin, + "autoreject" => EChannelOption.AutoReject, _ => null }; - string optionStr = option switch - { - ChannelOption.Normal => "不做特殊处理", - ChannelOption.PurgeOrigin => "抹除频道来源", - ChannelOption.AutoReject => "拒绝此频道的投稿", + string optionStr = option switch { + EChannelOption.Normal => "不做特殊处理", + EChannelOption.PurgeOrigin => "抹除频道来源", + EChannelOption.AutoReject => "拒绝此频道的投稿", _ => "未知的值", }; @@ -209,7 +212,7 @@ async Task exec() /// /// /// - [TextCmd("COMMAND", UserRights.SuperCmd, Description = "设置命令菜单")] + [TextCmd("COMMAND", EUserRights.SuperCmd, Description = "设置命令菜单")] public async Task ResponseCommand(Message message) { bool result = await _commandHandler.GetCommandsMenu(); @@ -221,7 +224,7 @@ public async Task ResponseCommand(Message message) /// /// /// - [TextCmd("RECALCPOST", UserRights.SuperCmd, Description = "重新计算用户投稿数量")] + [TextCmd("RECALCPOST", EUserRights.SuperCmd, Description = "重新计算用户投稿数量")] public async Task ResponseReCalcPost(Message message) { const int threads = 10; @@ -241,11 +244,10 @@ public async Task ResponseReCalcPost(Message message) break; } - var tasks = users.Select(async user => - { + var tasks = users.Select(async user => { int postCount = await _postService.Queryable().CountAsync(x => x.PosterUID == user.UserID); - int acceptCount = await _postService.Queryable().CountAsync(x => x.PosterUID == user.UserID && x.Status == PostStatus.Accepted); - int rejectCount = await _postService.Queryable().CountAsync(x => x.PosterUID == user.UserID && x.Status == PostStatus.Rejected); + int acceptCount = await _postService.Queryable().CountAsync(x => x.PosterUID == user.UserID && x.Status == EPostStatus.Accepted); + int rejectCount = await _postService.Queryable().CountAsync(x => x.PosterUID == user.UserID && x.Status == EPostStatus.Rejected); int expiredCount = await _postService.Queryable().CountAsync(x => x.PosterUID == user.UserID && x.Status < 0); int reviewCount = await _postService.Queryable().CountAsync(x => x.ReviewerUID == user.UserID && x.PosterUID != user.UserID); @@ -260,8 +262,7 @@ public async Task ResponseReCalcPost(Message message) effectCount++; - await _userService.Updateable(user).UpdateColumns(x => new - { + await _userService.Updateable(user).UpdateColumns(x => new { x.PostCount, x.AcceptCount, x.RejectCount, @@ -294,61 +295,59 @@ public async Task ResponseReCalcPost(Message message) /// /// /// - [TextCmd("MERGEPOST", UserRights.SuperCmd, Description = "迁移旧的稿件数据")] + [TextCmd("MERGEPOSTTAG", EUserRights.SuperCmd, Description = "迁移旧的稿件标签数据")] [Obsolete("迁移旧数据用")] - public async Task ResponseMergePost(Message message) + public async Task ResponseMergePostTag(Message message) { - const int threads = 10; + const int threads = 30; int startId = 1; int effectCount = 0; - int totalPosts = await _postService.Queryable().CountAsync(); + int totalPosts = await _oldPostService.Queryable().CountAsync(); var msg = await _botClient.SendCommandReply($"开始更新稿件表, 共计 {totalPosts} 条记录", message, autoDelete: false); while (startId <= totalPosts) { - var posts = await _postService.Queryable().Where(x => x.Id >= startId && x.Tags != BuildInTags.None).Take(threads).ToListAsync(); - if (!posts.Any()) + var oldOosts = await _oldPostService.Queryable().Where(x => x.Id >= startId && x.Tags != EBuildInTags.None).Take(threads).ToListAsync(); + if (!oldOosts.Any()) { break; } - var tasks = posts.Select(async post => - { - if (post.Tags != BuildInTags.None) + var tasks = oldOosts.Select(async oldPost => { + if (oldPost.Tags != EBuildInTags.None) { - var oldTag = post.Tags; - if (oldTag.HasFlag(BuildInTags.Spoiler)) + var oldTag = oldPost.Tags; + if (oldTag.HasFlag(EBuildInTags.Spoiler)) { - post.HasSpoiler = true; + oldPost.HasSpoiler = true; } int newTag = 0; - if (oldTag.HasFlag(BuildInTags.NSFW)) + if (oldTag.HasFlag(EBuildInTags.NSFW)) { newTag += 1; } - if (oldTag.HasFlag(BuildInTags.Friend)) + if (oldTag.HasFlag(EBuildInTags.Friend)) { newTag += 2; } - if (oldTag.HasFlag(BuildInTags.WanAn)) + if (oldTag.HasFlag(EBuildInTags.WanAn)) { newTag += 4; } - if (oldTag.HasFlag(BuildInTags.AIGraph)) + if (oldTag.HasFlag(EBuildInTags.AIGraph)) { newTag += 8; } - post.Tags = BuildInTags.None; - post.NewTags = newTag; - post.ModifyAt = DateTime.Now; + oldPost.Tags = EBuildInTags.None; + oldPost.NewTags = newTag; + oldPost.ModifyAt = DateTime.Now; effectCount++; - await _postService.Updateable(post).UpdateColumns(x => new - { + await _oldPostService.Updateable(oldPost).UpdateColumns(x => new { x.Tags, x.NewTags, x.ModifyAt @@ -358,7 +357,7 @@ public async Task ResponseMergePost(Message message) await Task.WhenAll(tasks); - startId = posts.Last().Id + 1; + startId = oldOosts.Last().Id + 1; _logger.LogInformation("更新进度 {startId} / {totalUsers}, 更新数量 {effectCount}", startId, totalPosts, effectCount); } @@ -373,12 +372,154 @@ public async Task ResponseMergePost(Message message) } } + /// + /// 迁移旧的稿件数据 + /// + /// + /// + [TextCmd("MERGEPOST", EUserRights.SuperCmd, Description = "迁移旧的稿件数据")] + [Obsolete("迁移旧数据用")] + public async Task ResponseMergePost(Message message) + { + const int threads = 30; + + int startId = 1; + int effectCount = 0; + + int totalPosts = await _oldPostService.Queryable().CountAsync(x => !x.Merged); + + var msg = await _botClient.SendCommandReply($"开始迁移稿件表, 共计 {totalPosts} 条记录", message, autoDelete: false); + + while (startId <= totalPosts) + { + var oldPosts = await _oldPostService.Queryable().Where(x => x.Id >= startId && !x.Merged).Take(threads).ToListAsync(); + if (!oldPosts.Any()) + { + break; + } + + var tasks = oldPosts.Select(async oldPost => { + + long channelId = -1, channelMsgId = -1; + if (oldPost.IsFromChannel) + { + ChannelOptions? channel = null; + + var name = oldPost.ChannelName; + var title = oldPost.ChannelTitle; + + if (name.EndsWith('~')) + { + name = name.Substring(0, name.Length - 1); + } + + var text = name.Split('/'); + if (text.Length >= 2) + { + if (!long.TryParse(text[1], out channelMsgId)) + { + channelMsgId = -1; + } + channel = await _channelOptionService.FetchChannelByNameOrTitle(text[0], title); + } + else + { + channel = await _channelOptionService.FetchChannelByNameOrTitle(name, title); + } + + if (channel != null) + { + channelId = channel.ChannelID; + } + } + + string reason = oldPost.Reason switch { + ERejectReason.Fuzzy => "模糊", + ERejectReason.Duplicate => "重复", + ERejectReason.Boring => "无趣", + ERejectReason.Confused => "没懂", + ERejectReason.Deny => "内容不合适", + ERejectReason.QRCode => "广告水印", + ERejectReason.Other => "其他原因", + ERejectReason.CustomReason => "自定义拒绝理由", + ERejectReason.AutoReject => "稿件审核超时", + _ => "", + }; + + bool countReject = oldPost.Status != EPostStatus.Rejected ? false : + (oldPost.Reason != ERejectReason.Fuzzy && oldPost.Reason != ERejectReason.Duplicate); + + var post = new NewPosts { + OriginChatID = oldPost.OriginChatID, + OriginMsgID = oldPost.OriginMsgID, + OriginActionChatID = oldPost.OriginChatID, + OriginActionMsgID = oldPost.ActionMsgID, + PublicMsgID = oldPost.PublicMsgID, + Anonymous = oldPost.Anonymous, + Text = oldPost.Text, + RawText = oldPost.RawText, + ChannelID = channelId, + ChannelMsgId = channelMsgId, + Status = oldPost.Status, + PostType = oldPost.PostType, + OriginMediaGroupID = "", + ReviewMediaGroupID = "", + PublishMediaGroupID = "", + Tags = oldPost.NewTags, + HasSpoiler = oldPost.HasSpoiler, + RejectReason = reason, + CountReject = countReject, + PosterUID = oldPost.PosterUID, + ReviewerUID = oldPost.ReviewerUID, + CreateAt = oldPost.CreateAt, + }; + + if (oldPost.IsDirectPost) + { + post.ReviewChatID = oldPost.OriginChatID; + post.ReviewMsgID = oldPost.OriginMsgID; + post.ReviewActionChatID = oldPost.OriginChatID; + post.ReviewActionMsgID = oldPost.ActionMsgID; + } + else + { + post.ReviewChatID = _channelService.ReviewGroup.Id; + post.ReviewMsgID = oldPost.ReviewMsgID; + post.ReviewActionChatID = _channelService.ReviewGroup.Id; + post.ReviewActionMsgID = oldPost.ManageMsgID; + } + + post.ModifyAt = DateTime.Now; + await _postService.InsertAsync(post); + + oldPost.Merged = true; + await _oldPostService.Updateable(oldPost).UpdateColumns(x => x.Merged).ExecuteCommandAsync(); + + }).ToList(); + + await Task.WhenAll(tasks); + + startId = oldPosts.Last().Id + 1; + + _logger.LogInformation("迁移进度 {startId} / {totalUsers}, 更新数量 {effectCount}", startId, totalPosts, effectCount); + } + + try + { + await _botClient.EditMessageTextAsync(msg, $"迁移稿件表完成, 更新了 {effectCount} 条记录"); + } + catch + { + await _botClient.SendCommandReply($"迁移稿件表完成, 更新了 {effectCount} 条记录", message, autoDelete: false); + } + } + /// /// 自动升级机器人 /// /// /// - [TextCmd("UPDATE", UserRights.SuperCmd, Description = "自动升级机器人")] + [TextCmd("UPDATE", EUserRights.SuperCmd, Description = "自动升级机器人")] public async Task ResponseUpdate(Message message) { async Task exec() diff --git a/XinjingdailyBot.Command/XinjingdailyBot.Command.csproj b/XinjingdailyBot.Command/XinjingdailyBot.Command.csproj index 0d9e40b8..31273259 100644 --- a/XinjingdailyBot.Command/XinjingdailyBot.Command.csproj +++ b/XinjingdailyBot.Command/XinjingdailyBot.Command.csproj @@ -1,14 +1,18 @@  - - Library - - - - - - - - + + Library + + + + + + + + + + + + \ No newline at end of file diff --git a/XinjingdailyBot.Infrastructure/Attribute/QueryCmdAttribute.cs b/XinjingdailyBot.Infrastructure/Attribute/QueryCmdAttribute.cs index 96801e77..74ce873c 100644 --- a/XinjingdailyBot.Infrastructure/Attribute/QueryCmdAttribute.cs +++ b/XinjingdailyBot.Infrastructure/Attribute/QueryCmdAttribute.cs @@ -24,7 +24,7 @@ public sealed class QueryCmdAttribute : System.Attribute /// /// 需求的权限 /// - public UserRights Rights { get; set; } = UserRights.None; + public EUserRights Rights { get; set; } = EUserRights.None; /// /// 创建特性 @@ -33,14 +33,14 @@ public sealed class QueryCmdAttribute : System.Attribute public QueryCmdAttribute(string command) { Command = command; - Rights = UserRights.None; + Rights = EUserRights.None; } /// /// 创建特性 /// /// /// - public QueryCmdAttribute(string command, UserRights rights) + public QueryCmdAttribute(string command, EUserRights rights) { Command = command; Rights = rights; diff --git a/XinjingdailyBot.Infrastructure/Attribute/TextCmdAttribute.cs b/XinjingdailyBot.Infrastructure/Attribute/TextCmdAttribute.cs index 40d7ab5e..bac227d8 100644 --- a/XinjingdailyBot.Infrastructure/Attribute/TextCmdAttribute.cs +++ b/XinjingdailyBot.Infrastructure/Attribute/TextCmdAttribute.cs @@ -24,7 +24,7 @@ public sealed class TextCmdAttribute : System.Attribute /// /// 需求的权限 /// - public UserRights Rights { get; set; } = UserRights.None; + public EUserRights Rights { get; set; } = EUserRights.None; /// /// 创建特性 @@ -33,14 +33,14 @@ public sealed class TextCmdAttribute : System.Attribute public TextCmdAttribute(string command) { Command = command; - Rights = UserRights.None; + Rights = EUserRights.None; } /// /// 创建特性 /// /// /// - public TextCmdAttribute(string command, UserRights rights) + public TextCmdAttribute(string command, EUserRights rights) { Command = command; Rights = rights; diff --git a/XinjingdailyBot.Infrastructure/BuildInfo.cs b/XinjingdailyBot.Infrastructure/BuildInfo.cs index 4eb3b7b8..5daee792 100644 --- a/XinjingdailyBot.Infrastructure/BuildInfo.cs +++ b/XinjingdailyBot.Infrastructure/BuildInfo.cs @@ -30,5 +30,7 @@ public static class BuildInfo public static bool CanUpdate => false; public static string Variant => "source"; #endif + public static string Author => "chr233"; + public static string Repo => "https://github.com/chr233/XinjingdailyBot/"; } } diff --git a/XinjingdailyBot.Infrastructure/Enums/AdMode.cs b/XinjingdailyBot.Infrastructure/Enums/EAdMode.cs similarity index 97% rename from XinjingdailyBot.Infrastructure/Enums/AdMode.cs rename to XinjingdailyBot.Infrastructure/Enums/EAdMode.cs index 5121396a..f0439668 100644 --- a/XinjingdailyBot.Infrastructure/Enums/AdMode.cs +++ b/XinjingdailyBot.Infrastructure/Enums/EAdMode.cs @@ -4,7 +4,7 @@ /// 广告发布位置 /// [Flags] - public enum AdMode + public enum EAdMode { /// /// 不发布 diff --git a/XinjingdailyBot.Infrastructure/Enums/BanType.cs b/XinjingdailyBot.Infrastructure/Enums/EBanType.cs similarity index 93% rename from XinjingdailyBot.Infrastructure/Enums/BanType.cs rename to XinjingdailyBot.Infrastructure/Enums/EBanType.cs index d186c480..6c2c7439 100644 --- a/XinjingdailyBot.Infrastructure/Enums/BanType.cs +++ b/XinjingdailyBot.Infrastructure/Enums/EBanType.cs @@ -3,7 +3,7 @@ /// /// 封禁类型 /// - public enum BanType : byte + public enum EBanType : byte { /// /// 解封 diff --git a/XinjingdailyBot.Infrastructure/Enums/BuildInTags.cs b/XinjingdailyBot.Infrastructure/Enums/EBuildInTags.cs similarity index 95% rename from XinjingdailyBot.Infrastructure/Enums/BuildInTags.cs rename to XinjingdailyBot.Infrastructure/Enums/EBuildInTags.cs index 6c6c03ad..2c1b7206 100644 --- a/XinjingdailyBot.Infrastructure/Enums/BuildInTags.cs +++ b/XinjingdailyBot.Infrastructure/Enums/EBuildInTags.cs @@ -5,7 +5,7 @@ /// [Flags] [Obsolete("过时的方法")] - public enum BuildInTags : int + public enum EBuildInTags : int { /// /// 无 diff --git a/XinjingdailyBot.Infrastructure/Enums/ChannelOption.cs b/XinjingdailyBot.Infrastructure/Enums/EChannelOption.cs similarity index 92% rename from XinjingdailyBot.Infrastructure/Enums/ChannelOption.cs rename to XinjingdailyBot.Infrastructure/Enums/EChannelOption.cs index 28e14a30..f0d71d91 100644 --- a/XinjingdailyBot.Infrastructure/Enums/ChannelOption.cs +++ b/XinjingdailyBot.Infrastructure/Enums/EChannelOption.cs @@ -3,7 +3,7 @@ /// /// 频道封禁类型 /// - public enum ChannelOption : byte + public enum EChannelOption : byte { /// /// 不做处理 diff --git a/XinjingdailyBot.Infrastructure/Enums/PostStatus.cs b/XinjingdailyBot.Infrastructure/Enums/EPostStatus.cs similarity index 96% rename from XinjingdailyBot.Infrastructure/Enums/PostStatus.cs rename to XinjingdailyBot.Infrastructure/Enums/EPostStatus.cs index 57c926b3..bf56cbff 100644 --- a/XinjingdailyBot.Infrastructure/Enums/PostStatus.cs +++ b/XinjingdailyBot.Infrastructure/Enums/EPostStatus.cs @@ -3,7 +3,7 @@ /// /// 稿件状态 /// - public enum PostStatus : int + public enum EPostStatus : int { /// /// 确认投稿超时 diff --git a/XinjingdailyBot.Infrastructure/Enums/RejectReason.cs b/XinjingdailyBot.Infrastructure/Enums/ERejectReason.cs similarity index 94% rename from XinjingdailyBot.Infrastructure/Enums/RejectReason.cs rename to XinjingdailyBot.Infrastructure/Enums/ERejectReason.cs index d29467a9..14688632 100644 --- a/XinjingdailyBot.Infrastructure/Enums/RejectReason.cs +++ b/XinjingdailyBot.Infrastructure/Enums/ERejectReason.cs @@ -3,7 +3,8 @@ /// /// 拒稿原因 /// - public enum RejectReason : byte + [Obsolete("弃用")] + public enum ERejectReason : byte { /// /// 未拒绝 diff --git a/XinjingdailyBot.Infrastructure/Enums/UserRights.cs b/XinjingdailyBot.Infrastructure/Enums/EUserRights.cs similarity index 98% rename from XinjingdailyBot.Infrastructure/Enums/UserRights.cs rename to XinjingdailyBot.Infrastructure/Enums/EUserRights.cs index 3fe93fcd..5b65755c 100644 --- a/XinjingdailyBot.Infrastructure/Enums/UserRights.cs +++ b/XinjingdailyBot.Infrastructure/Enums/EUserRights.cs @@ -4,7 +4,7 @@ /// 用户权限 /// [Flags] - public enum UserRights : byte + public enum EUserRights : byte { /// /// 无权限 diff --git a/XinjingdailyBot.Infrastructure/Extensions/BotClientExtension.cs b/XinjingdailyBot.Infrastructure/Extensions/BotClientExtension.cs index c0a5c8e6..ebf7c1a9 100644 --- a/XinjingdailyBot.Infrastructure/Extensions/BotClientExtension.cs +++ b/XinjingdailyBot.Infrastructure/Extensions/BotClientExtension.cs @@ -126,8 +126,7 @@ public static async Task SendCommandReply( if (delete) { - _ = Task.Run(async () => - { + _ = Task.Run(async () => { await Task.Delay(TimeSpan.FromSeconds(30)); try { diff --git a/XinjingdailyBot.Infrastructure/Extensions/LoggerExtensions.cs b/XinjingdailyBot.Infrastructure/Extensions/LoggerExtensions.cs index 22cdcc10..5864fafb 100644 --- a/XinjingdailyBot.Infrastructure/Extensions/LoggerExtensions.cs +++ b/XinjingdailyBot.Infrastructure/Extensions/LoggerExtensions.cs @@ -46,8 +46,7 @@ public static void LogUpdate(this ILogger logger, Update update) /// public static void LogMessage(this ILogger logger, Message message) { - string content = message.Type switch - { + string content = message.Type switch { MessageType.Text => $"[文本] {message.Text}", MessageType.Photo => $"[图片] {message.Caption}", MessageType.Audio => $"[音频] {message.Caption}", @@ -69,8 +68,7 @@ public static void LogMessage(this ILogger logger, Message message) var chat = message.Chat; - string chatFrom = chat.Type switch - { + string chatFrom = chat.Type switch { ChatType.Private => $"【私聊|{chat.FirstName}{chat.LastName}】", ChatType.Group => $"【群组|{chat.Title}】", ChatType.Channel => $"【频道|{chat.Title}】", diff --git a/XinjingdailyBot.Infrastructure/Localization/Langs.Designer.cs b/XinjingdailyBot.Infrastructure/Localization/Langs.Designer.cs index 0e94a5bf..05f25204 100644 --- a/XinjingdailyBot.Infrastructure/Localization/Langs.Designer.cs +++ b/XinjingdailyBot.Infrastructure/Localization/Langs.Designer.cs @@ -87,6 +87,24 @@ public static string BanedUserTips { } } + /// + /// 查找类似 Copyright © 2022-2023 {0} 的本地化字符串。 + /// + public static string Copyright { + get { + return ResourceManager.GetString("Copyright", resourceCulture); + } + } + + /// + /// 查找类似 ========================================================== 的本地化字符串。 + /// + public static string Line { + get { + return ResourceManager.GetString("Line", resourceCulture); + } + } + /// /// 查找类似 没有权限 的本地化字符串。 /// @@ -366,6 +384,15 @@ public static string UnbanedUserTips { } } + /// + /// 查找类似 Version: {0} - {1} 的本地化字符串。 + /// + public static string Version { + get { + return ResourceManager.GetString("Version", resourceCulture); + } + } + /// /// 查找类似 您受到了一次警告, 理由: {0} 的本地化字符串。 /// diff --git a/XinjingdailyBot.Infrastructure/Localization/Langs.resx b/XinjingdailyBot.Infrastructure/Localization/Langs.resx index 92e32086..29506310 100644 --- a/XinjingdailyBot.Infrastructure/Localization/Langs.resx +++ b/XinjingdailyBot.Infrastructure/Localization/Langs.resx @@ -225,4 +225,13 @@ ⚠️ NSFW 提前预警 ⚠️ + + ========================================================== + + + Copyright © 2022-2023 {0} + + + Version: {0} - {1} + \ No newline at end of file diff --git a/XinjingdailyBot.Infrastructure/Model/AssemblyMethod.cs b/XinjingdailyBot.Infrastructure/Model/AssemblyMethod.cs index 12442764..06f4cb46 100644 --- a/XinjingdailyBot.Infrastructure/Model/AssemblyMethod.cs +++ b/XinjingdailyBot.Infrastructure/Model/AssemblyMethod.cs @@ -7,9 +7,9 @@ public sealed record AssemblyMethod { public MethodInfo Method { get; set; } public string? Description { get; set; } - public UserRights Rights { get; set; } + public EUserRights Rights { get; set; } - public AssemblyMethod(MethodInfo method, string? description, UserRights rights) + public AssemblyMethod(MethodInfo method, string? description, EUserRights rights) { Method = method; Description = description; diff --git a/XinjingdailyBot.Infrastructure/RegexUtils.cs b/XinjingdailyBot.Infrastructure/RegexUtils.cs new file mode 100644 index 00000000..9874b204 --- /dev/null +++ b/XinjingdailyBot.Infrastructure/RegexUtils.cs @@ -0,0 +1,20 @@ +using System.Text.RegularExpressions; + +namespace XinjingdailyBot.Infrastructure +{ + public static partial class RegexUtils + { + /// + /// 匹配HashTag + /// + /// + [GeneratedRegex("(^#\\S+)|(\\s#\\S+)")] + public static partial Regex MatchHashTag(); + /// + /// 匹配整个空行 + /// + /// + [GeneratedRegex("^\\s*$")] + public static partial Regex MatchBlankLine(); + } +} diff --git a/XinjingdailyBot.Infrastructure/XinjingdailyBot.Infrastructure.csproj b/XinjingdailyBot.Infrastructure/XinjingdailyBot.Infrastructure.csproj index 85438af0..de8714a9 100644 --- a/XinjingdailyBot.Infrastructure/XinjingdailyBot.Infrastructure.csproj +++ b/XinjingdailyBot.Infrastructure/XinjingdailyBot.Infrastructure.csproj @@ -1,37 +1,41 @@  - - Library - + + Library + - - - - - + + + + + - - - Emojis.resx - True - True - - - Langs.resx - True - True - - + + + - - - Emojis.Designer.cs - PublicResXFileCodeGenerator - - - Langs.Designer.cs - PublicResXFileCodeGenerator - - + + + Emojis.resx + True + True + + + Langs.resx + True + True + + + + + + Emojis.Designer.cs + PublicResXFileCodeGenerator + + + Langs.Designer.cs + PublicResXFileCodeGenerator + + \ No newline at end of file diff --git a/XinjingdailyBot.Interface/Bot/Common/IChannelService.cs b/XinjingdailyBot.Interface/Bot/Common/IChannelService.cs index c8a5c17a..182cf068 100644 --- a/XinjingdailyBot.Interface/Bot/Common/IChannelService.cs +++ b/XinjingdailyBot.Interface/Bot/Common/IChannelService.cs @@ -43,11 +43,24 @@ public interface IChannelService /// /// bool IsChannelMessage(long chatId); + /// + /// 判断是不是频道的消息 + /// + /// + /// + bool IsChannelMessage(Chat chat); + /// /// 判断是不是关联群组的消息 /// /// /// bool IsGroupMessage(long chatId); + /// + /// 判断是不是关联群组的消息 + /// + /// + /// + bool IsGroupMessage(Chat chat); } } diff --git a/XinjingdailyBot.Interface/Data/IChannelOptionService.cs b/XinjingdailyBot.Interface/Data/IChannelOptionService.cs index 75b2a402..5b0b5e94 100644 --- a/XinjingdailyBot.Interface/Data/IChannelOptionService.cs +++ b/XinjingdailyBot.Interface/Data/IChannelOptionService.cs @@ -1,4 +1,5 @@ -using XinjingdailyBot.Infrastructure.Enums; +using Telegram.Bot.Types; +using XinjingdailyBot.Infrastructure.Enums; using XinjingdailyBot.Interface.Data.Base; using XinjingdailyBot.Model.Models; @@ -6,6 +7,19 @@ namespace XinjingdailyBot.Interface.Data { public interface IChannelOptionService : IBaseService { + /// + /// 根据ID获取频道 + /// + /// + /// + Task FetchChannelByChannelId(long channelId); + /// + /// 根据UserName获取频道 + /// + /// + /// + Task FetchChannelByNameOrTitle(string channelName,string channelTitle); + /// /// 通过频道名称获取频道ID /// @@ -15,17 +29,15 @@ public interface IChannelOptionService : IBaseService /// /// 获取频道设定 /// - /// - /// - /// + /// /// - Task FetchChannelOption(long channelId, string? channelName, string? channelTitle); + Task FetchChannelOption(Chat channelChat); /// /// 更新频道设定 /// /// /// /// - Task UpdateChannelOptionById(long channelId, ChannelOption channelOption); + Task UpdateChannelOptionById(long channelId, EChannelOption channelOption); } } diff --git a/XinjingdailyBot.Interface/Data/IChatStateService.cs b/XinjingdailyBot.Interface/Data/IChatStateService.cs deleted file mode 100644 index 2316750a..00000000 --- a/XinjingdailyBot.Interface/Data/IChatStateService.cs +++ /dev/null @@ -1,9 +0,0 @@ -using XinjingdailyBot.Interface.Data.Base; -using XinjingdailyBot.Model.Models; - -namespace XinjingdailyBot.Interface.Data -{ - public interface IChatStateService : IBaseService - { - } -} diff --git a/XinjingdailyBot.Interface/Data/IMediaGroupService.cs b/XinjingdailyBot.Interface/Data/IMediaGroupService.cs index 23392a7b..be123ed4 100644 --- a/XinjingdailyBot.Interface/Data/IMediaGroupService.cs +++ b/XinjingdailyBot.Interface/Data/IMediaGroupService.cs @@ -39,5 +39,12 @@ public interface IMediaGroupService /// /// Task QueryMediaGroup(Chat chat, long msgId); + /// + /// 查询媒体组消息 + /// + /// + /// + /// + Task QueryMediaGroup(long chatId, int msgId); } } diff --git a/XinjingdailyBot.Interface/Data/IPostService.cs b/XinjingdailyBot.Interface/Data/IPostService.cs index aaf413c8..d8d19d08 100644 --- a/XinjingdailyBot.Interface/Data/IPostService.cs +++ b/XinjingdailyBot.Interface/Data/IPostService.cs @@ -4,7 +4,7 @@ namespace XinjingdailyBot.Interface.Data { - public interface IPostService : IBaseService + public interface IPostService : IBaseService { /// /// 文字投稿长度上限 @@ -18,7 +18,7 @@ public interface IPostService : IBaseService /// /// /// - Task AcceptPost(Posts post, Users dbUser, CallbackQuery callbackQuery); + Task AcceptPost(NewPosts post, Users dbUser, CallbackQuery callbackQuery); /// /// 检查用户是否达到每日投稿上限 /// @@ -30,19 +30,13 @@ public interface IPostService : IBaseService /// /// /// - Task FetchPostFromReviewCallbackQuery(CallbackQuery message); + Task FetchPostFromCallbackQuery(CallbackQuery message); /// /// 从回复的消息获取稿件 /// /// /// - Task FetchPostFromReplyToMessage(Message message); - /// - /// 从确认投稿回调中获取稿件 - /// - /// - /// - Task FetchPostFromConfirmCallbackQuery(CallbackQuery query); + Task FetchPostFromReplyToMessage(Message message); /// /// 处理多媒体投稿(mediaGroup) @@ -72,7 +66,7 @@ public interface IPostService : IBaseService /// /// /// - Task RejetPost(Posts post, Users dbUser, string rejectReason); + Task RejetPost(NewPosts post, Users dbUser, RejectReasons rejectReason); /// /// 设置稿件Tag /// @@ -80,7 +74,7 @@ public interface IPostService : IBaseService /// /// /// - Task SetPostTag(Posts post, int tagId, CallbackQuery callbackQuery); + Task SetPostTag(NewPosts post, int tagId, CallbackQuery callbackQuery); /// /// 设置稿件Tag /// @@ -88,6 +82,6 @@ public interface IPostService : IBaseService /// /// /// - Task SetPostTag(Posts post, string payload, CallbackQuery callbackQuery); + Task SetPostTag(NewPosts post, string payload, CallbackQuery callbackQuery); } } diff --git a/XinjingdailyBot.Interface/Helper/IMarkupHelperService.cs b/XinjingdailyBot.Interface/Helper/IMarkupHelperService.cs index 83a92f75..71027fd3 100644 --- a/XinjingdailyBot.Interface/Helper/IMarkupHelperService.cs +++ b/XinjingdailyBot.Interface/Helper/IMarkupHelperService.cs @@ -18,7 +18,7 @@ public interface IMarkupHelperService /// /// /// - InlineKeyboardMarkup? LinkToOriginPostKeyboard(Posts post); + InlineKeyboardMarkup? LinkToOriginPostKeyboard(NewPosts post); /// /// 跳转链接键盘 /// @@ -45,7 +45,7 @@ public interface IMarkupHelperService /// /// /// - InlineKeyboardMarkup QueryPostMenuKeyboard(Users dbUser, Posts post); + InlineKeyboardMarkup QueryPostMenuKeyboard(Users dbUser, NewPosts post); /// /// 获取随机投稿键盘 /// @@ -60,7 +60,7 @@ public interface IMarkupHelperService /// 获取随机投稿键盘 /// /// - InlineKeyboardMarkup RandomPostMenuKeyboard(Users dbUser, Posts post, int tagId, string postType); + InlineKeyboardMarkup RandomPostMenuKeyboard(Users dbUser, NewPosts post, int tagId, string postType); /// /// 审核键盘A(选择稿件Tag) /// diff --git a/XinjingdailyBot.Interface/Helper/ITextHelperService.cs b/XinjingdailyBot.Interface/Helper/ITextHelperService.cs index 9e78ef2e..484c1eb4 100644 --- a/XinjingdailyBot.Interface/Helper/ITextHelperService.cs +++ b/XinjingdailyBot.Interface/Helper/ITextHelperService.cs @@ -1,5 +1,4 @@ using Telegram.Bot.Types; -using XinjingdailyBot.Infrastructure.Enums; using XinjingdailyBot.Model.Models; namespace XinjingdailyBot.Interface.Helper @@ -59,14 +58,14 @@ public interface ITextHelperService /// /// /// - string MakePoster(Posts post, Users poster); + string MakePoster(NewPosts post, Users poster, ChannelOptions? channel); /// /// 生成稿件 /// /// /// /// - string MakePostText(Posts post, Users poster); + string MakePostText(NewPosts post, Users poster, ChannelOptions? channel); /// /// 生成审核消息(待审核) /// @@ -109,11 +108,5 @@ public interface ITextHelperService /// /// string PureText(string? text); - /// - /// 格式化RejectReason - /// - /// - /// - string RejectReasonToString(RejectReason rejectReason); } } diff --git a/XinjingdailyBot.Interface/XinjingdailyBot.Interface.csproj b/XinjingdailyBot.Interface/XinjingdailyBot.Interface.csproj index 992a9fbf..bf16d3b9 100644 --- a/XinjingdailyBot.Interface/XinjingdailyBot.Interface.csproj +++ b/XinjingdailyBot.Interface/XinjingdailyBot.Interface.csproj @@ -1,13 +1,17 @@  - - Library - - - - - - - + + Library + + + + + + + + + + + diff --git a/XinjingdailyBot.Model/Base/PagedInfo.cs b/XinjingdailyBot.Model/Base/PagedInfo.cs index 4c0cd3a2..fa0e5711 100644 --- a/XinjingdailyBot.Model/Base/PagedInfo.cs +++ b/XinjingdailyBot.Model/Base/PagedInfo.cs @@ -20,10 +20,8 @@ public class PagedInfo /// /// 总页数 /// - public int TotalPage - { - get - { + public int TotalPage { + get { if (TotalNum > 0) { return TotalNum % PageSize == 0 ? TotalNum / PageSize : TotalNum / PageSize + 1; diff --git a/XinjingdailyBot.Model/Base/PagerInfo.cs b/XinjingdailyBot.Model/Base/PagerInfo.cs index 302db6b3..a2f164cd 100644 --- a/XinjingdailyBot.Model/Base/PagerInfo.cs +++ b/XinjingdailyBot.Model/Base/PagerInfo.cs @@ -17,10 +17,8 @@ public class PagerInfo /// /// 总页数 /// - public int TotalPage - { - get - { + public int TotalPage { + get { return TotalNum > 0 ? TotalNum % PageSize == 0 ? TotalNum / PageSize : TotalNum / PageSize + 1 : 0; } } diff --git a/XinjingdailyBot.Model/Columns/ICreateAt.cs b/XinjingdailyBot.Model/Columns/ICreateAt.cs new file mode 100644 index 00000000..98cca226 --- /dev/null +++ b/XinjingdailyBot.Model/Columns/ICreateAt.cs @@ -0,0 +1,12 @@ +namespace XinjingdailyBot.Model.Columns; + +/// +/// 创建时间 +/// +public interface ICreateAt +{ + /// + /// 创建时间 + /// + DateTime CreateAt { get; set; } +} diff --git a/XinjingdailyBot.Model/Columns/IExecuteAt.cs b/XinjingdailyBot.Model/Columns/IExecuteAt.cs new file mode 100644 index 00000000..5d0eec15 --- /dev/null +++ b/XinjingdailyBot.Model/Columns/IExecuteAt.cs @@ -0,0 +1,12 @@ +namespace XinjingdailyBot.Model.Columns; + +/// +/// 命令调用时间 +/// +public interface IExecuteAt +{ + /// + /// 命令调用时间 + /// + DateTime ExecuteAt { get; set; } +} diff --git a/XinjingdailyBot.Model/Columns/IExpiredAt.cs b/XinjingdailyBot.Model/Columns/IExpiredAt.cs new file mode 100644 index 00000000..810f3222 --- /dev/null +++ b/XinjingdailyBot.Model/Columns/IExpiredAt.cs @@ -0,0 +1,12 @@ +namespace XinjingdailyBot.Model.Columns; + +/// +/// 过期时间 +/// +public interface IExpiredAt +{ + /// + /// 修改时间 + /// + DateTime ExpiredAt { get; set; } +} diff --git a/XinjingdailyBot.Model/Columns/IModifyAt.cs b/XinjingdailyBot.Model/Columns/IModifyAt.cs new file mode 100644 index 00000000..0b08992e --- /dev/null +++ b/XinjingdailyBot.Model/Columns/IModifyAt.cs @@ -0,0 +1,12 @@ +namespace XinjingdailyBot.Model.Columns; + +/// +/// 修改时间 +/// +public interface IModifyAt +{ + /// + /// 修改时间 + /// + DateTime ModifyAt { get; set; } +} diff --git a/XinjingdailyBot.Model/Models/Advertises.cs b/XinjingdailyBot.Model/Models/Advertises.cs index 9914fc0a..3aee26aa 100644 --- a/XinjingdailyBot.Model/Models/Advertises.cs +++ b/XinjingdailyBot.Model/Models/Advertises.cs @@ -1,11 +1,12 @@ using SqlSugar; using XinjingdailyBot.Infrastructure.Enums; using XinjingdailyBot.Model.Base; +using XinjingdailyBot.Model.Columns; namespace XinjingdailyBot.Model.Models { [SugarTable("ad", TableDescription = "广告投放")] - public sealed record Advertises : BaseModel + public sealed record Advertises : BaseModel, ICreateAt { [SugarColumn(IsPrimaryKey = true, IsIdentity = true)] public int Id { get; set; } @@ -31,7 +32,7 @@ public sealed record Advertises : BaseModel /// /// 广告发布位置 /// - public AdMode Mode { get; set; } = AdMode.None; + public EAdMode Mode { get; set; } = EAdMode.None; /// /// 展示权重, 数值越大概率越高, 0为不展示 @@ -57,9 +58,7 @@ public sealed record Advertises : BaseModel /// public DateTime ExpireAt { get; set; } = DateTime.MaxValue; - /// - /// 创建时间 - /// + /// public DateTime CreateAt { get; set; } = DateTime.Now; } } diff --git a/XinjingdailyBot.Model/Models/BanRecords.cs b/XinjingdailyBot.Model/Models/BanRecords.cs index 660669d0..e542417d 100644 --- a/XinjingdailyBot.Model/Models/BanRecords.cs +++ b/XinjingdailyBot.Model/Models/BanRecords.cs @@ -28,7 +28,7 @@ public sealed record BanRecords : BaseModel /// /// 是否封禁 true: 封禁, false: 解封 /// - public BanType Type { get; set; } = BanType.UnBan; + public EBanType Type { get; set; } = EBanType.UnBan; /// /// 封禁时间 /// diff --git a/XinjingdailyBot.Model/Models/ChannelOptions.cs b/XinjingdailyBot.Model/Models/ChannelOptions.cs index 131561af..d067fcc6 100644 --- a/XinjingdailyBot.Model/Models/ChannelOptions.cs +++ b/XinjingdailyBot.Model/Models/ChannelOptions.cs @@ -27,7 +27,7 @@ public sealed record ChannelOptions : BaseModel /// /// 封禁类型 /// - public ChannelOption Option { get; set; } = ChannelOption.Normal; + public EChannelOption Option { get; set; } = EChannelOption.Normal; public int Count { get; set; } diff --git a/XinjingdailyBot.Model/Models/ChatState.cs b/XinjingdailyBot.Model/Models/ChatState.cs deleted file mode 100644 index 2bdd1451..00000000 --- a/XinjingdailyBot.Model/Models/ChatState.cs +++ /dev/null @@ -1,22 +0,0 @@ -using SqlSugar; -using XinjingdailyBot.Model.Base; - -namespace XinjingdailyBot.Model.Models -{ - /// - /// 审核投票表 - /// - [SugarTable("chat", TableDescription = "聊天模式")] - public sealed record ChatState : BaseModel - { - /// - /// 用户Id - /// - [SugarColumn(IsPrimaryKey = true)] - public long UserId { get; set; } - /// - /// 会话状态 - /// - public bool InChat { get; set; } - } -} diff --git a/XinjingdailyBot.Model/Models/CmdRecords.cs b/XinjingdailyBot.Model/Models/CmdRecords.cs index 51730a4a..464a4364 100644 --- a/XinjingdailyBot.Model/Models/CmdRecords.cs +++ b/XinjingdailyBot.Model/Models/CmdRecords.cs @@ -1,5 +1,6 @@ using SqlSugar; using XinjingdailyBot.Model.Base; +using XinjingdailyBot.Model.Columns; namespace XinjingdailyBot.Model.Models { @@ -10,7 +11,7 @@ namespace XinjingdailyBot.Model.Models [SugarIndex("index_cid", nameof(ChatID), OrderByType.Asc)] [SugarIndex("index_mid", nameof(MessageID), OrderByType.Asc)] [SugarIndex("index_uid", nameof(UserID), OrderByType.Asc)] - public sealed record CmdRecords : BaseModel + public sealed record CmdRecords : BaseModel, IExecuteAt { [SugarColumn(IsPrimaryKey = true, IsIdentity = true)] public int Id { get; set; } @@ -49,9 +50,8 @@ public sealed record CmdRecords : BaseModel /// public bool Error { get; set; } - /// - /// 记录命令调用时间 - /// + /// + public DateTime ExecuteAt { get; set; } = DateTime.Now; } } diff --git a/XinjingdailyBot.Model/Models/Contexts.cs b/XinjingdailyBot.Model/Models/Contexts.cs deleted file mode 100644 index e1be9293..00000000 --- a/XinjingdailyBot.Model/Models/Contexts.cs +++ /dev/null @@ -1,17 +0,0 @@ -using SqlSugar; - -namespace XinjingdailyBot.Model.Models -{ - [SugarTable("context")] - public sealed record Contexts - { - /// - /// 用户ID - /// - public int UserID { get; set; } - /// - /// 上下文模式 - /// - public string Mode { get; set; } = ""; - } -} diff --git a/XinjingdailyBot.Model/Models/Dialogue.cs b/XinjingdailyBot.Model/Models/Dialogue.cs index 7f929454..95db08b8 100644 --- a/XinjingdailyBot.Model/Models/Dialogue.cs +++ b/XinjingdailyBot.Model/Models/Dialogue.cs @@ -1,10 +1,12 @@ using SqlSugar; using XinjingdailyBot.Model.Base; +using XinjingdailyBot.Model.Columns; namespace XinjingdailyBot.Model.Models { [SugarTable("dialogue", TableDescription = "消息记录")] - public sealed record Dialogue : BaseModel + [SugarIndex("index_chat", nameof(ChatID), OrderByType.Asc, nameof(MessageID), OrderByType.Asc, true)] + public sealed record Dialogue : BaseModel, ICreateAt { [SugarColumn(IsPrimaryKey = true, IsIdentity = true)] public int Id { get; set; } @@ -37,9 +39,9 @@ public sealed record Dialogue : BaseModel /// 消息类型 /// public string Type { get; set; } = ""; - /// - /// 消息事件 - /// - public DateTime Date { get; set; } = DateTime.Now; + + /// + [SugarColumn(OldColumnName = "Data", DefaultValue = "1970-01-01 00:00:00")] + public DateTime CreateAt { get; set; } } } diff --git a/XinjingdailyBot.Model/Models/Groups.cs b/XinjingdailyBot.Model/Models/Groups.cs index c4f67909..18895442 100644 --- a/XinjingdailyBot.Model/Models/Groups.cs +++ b/XinjingdailyBot.Model/Models/Groups.cs @@ -19,6 +19,6 @@ public sealed record Groups : BaseModel /// /// 默认权限 /// - public UserRights DefaultRight { get; set; } = UserRights.None; + public EUserRights DefaultRight { get; set; } = EUserRights.None; } } diff --git a/XinjingdailyBot.Model/Models/MediaGroups.cs b/XinjingdailyBot.Model/Models/MediaGroups.cs index f56979df..c8c80d1f 100644 --- a/XinjingdailyBot.Model/Models/MediaGroups.cs +++ b/XinjingdailyBot.Model/Models/MediaGroups.cs @@ -1,12 +1,13 @@ using SqlSugar; using XinjingdailyBot.Model.Base; +using XinjingdailyBot.Model.Columns; namespace XinjingdailyBot.Model.Models { [SugarTable("post_group", TableDescription = "媒体组稿件记录")] - [SugarIndex("index_msgid", nameof(ChatID), OrderByType.Asc, nameof(MessageID), OrderByType.Asc)] + [SugarIndex("index_msg", nameof(ChatID), OrderByType.Asc, nameof(MessageID), OrderByType.Asc)] [SugarIndex("index_groupid", nameof(MediaGroupID), OrderByType.Asc)] - public sealed record MediaGroups : BaseModel + public sealed record MediaGroups : BaseModel, ICreateAt { [SugarColumn(IsPrimaryKey = true, IsIdentity = true)] public int Id { get; set; } @@ -22,9 +23,7 @@ public sealed record MediaGroups : BaseModel /// 稿件ID /// public string MediaGroupID { get; set; } = ""; - /// - /// 创建时间 - /// + /// public DateTime CreateAt { get; set; } = DateTime.Now; } } diff --git a/XinjingdailyBot.Model/Models/NameHistory.cs b/XinjingdailyBot.Model/Models/NameHistory.cs index a58b1301..2dd8f2dc 100644 --- a/XinjingdailyBot.Model/Models/NameHistory.cs +++ b/XinjingdailyBot.Model/Models/NameHistory.cs @@ -22,7 +22,7 @@ public sealed record NameHistory : BaseModel /// /// 用户昵称 名 /// - public string LastName { get; set; } + public string LastName { get; set; } = ""; /// /// 添加日期 /// diff --git a/XinjingdailyBot.Model/Models/NewPosts.cs b/XinjingdailyBot.Model/Models/NewPosts.cs new file mode 100644 index 00000000..f44db4d2 --- /dev/null +++ b/XinjingdailyBot.Model/Models/NewPosts.cs @@ -0,0 +1,169 @@ +using SqlSugar; +using Telegram.Bot.Types.Enums; +using XinjingdailyBot.Infrastructure.Enums; +using XinjingdailyBot.Model.Base; +using XinjingdailyBot.Model.Columns; + +namespace XinjingdailyBot.Model.Models +{ + [SugarTable("new_post", TableDescription = "投稿记录")] + [SugarIndex("index_origin", nameof(OriginChatID), OrderByType.Asc, nameof(OriginMsgID), OrderByType.Asc)] + [SugarIndex("index_originaction", nameof(OriginActionChatID), OrderByType.Asc, nameof(OriginActionMsgID), OrderByType.Asc)] + [SugarIndex("index_review", nameof(ReviewChatID), OrderByType.Asc, nameof(ReviewMsgID), OrderByType.Asc)] + [SugarIndex("index_reviewaction", nameof(ReviewActionChatID), OrderByType.Asc, nameof(ReviewActionMsgID), OrderByType.Asc)] + [SugarIndex("index_origin_media_group_id", nameof(OriginMediaGroupID), OrderByType.Asc)] + [SugarIndex("index_review_media_group_id", nameof(ReviewMediaGroupID), OrderByType.Asc)] + [SugarIndex("index_post_media_group_id", nameof(PublishMediaGroupID), OrderByType.Asc)] + [SugarIndex("index_posterid", nameof(PosterUID), OrderByType.Asc)] + [SugarIndex("index_reviewerid", nameof(ReviewerUID), OrderByType.Asc)] + [SugarIndex("index_status_modifyat", nameof(Status), OrderByType.Asc, nameof(ModifyAt), OrderByType.Asc)] + public sealed record NewPosts : BaseModel, IModifyAt, ICreateAt + { + [SugarColumn(IsPrimaryKey = true, IsIdentity = true)] + public int Id { get; set; } + /// + /// 原始消息会话ID + /// + public long OriginChatID { get; set; } = -1; + /// + /// 原始消息ID + /// + public long OriginMsgID { get; set; } = -1; + + /// + /// 投稿控制消息会话ID + /// + public long OriginActionChatID { get; set; } = -1; + + /// + /// 投稿控制消息ID + /// + public long OriginActionMsgID { get; set; } = -1; + + /// + /// 审核消息会话ID + /// + public long ReviewChatID { get; set; } = -1; + /// + /// 审核群消息ID + /// + public long ReviewMsgID { get; set; } = -1; + + /// + /// 审核群控制消息会话ID + /// + public long ReviewActionChatID { get; set; } = -1; + /// + /// 审核群控制消息ID + /// + public long ReviewActionMsgID { get; set; } = -1; + + /// + /// 发布频道或拒绝频道的消息Id + /// + public long PublicMsgID { get; set; } = -1; + + /// + /// 是否为直接投稿 + /// + [SugarColumn(IsIgnore = true)] + public bool IsDirectPost => OriginActionChatID == ReviewActionChatID; + + /// + /// 匿名投稿 + /// + public bool Anonymous { get; set; } + + /// + /// 投稿描述(过滤#标签和链接) + /// + [SugarColumn(Length = 2000)] + public string Text { get; set; } = ""; + /// + /// 投稿原始描述 + /// + [SugarColumn(Length = 2000)] + public string RawText { get; set; } = ""; + + /// + /// 来源频道ID + /// + public long ChannelID { get; set; } = -1; + /// + /// 来源频道链接 + /// + public long ChannelMsgId { get; set; } = -1; + /// + /// 是否为频道转发 + /// + [SugarColumn(IsIgnore = true)] + public bool IsFromChannel => ChannelID != -1; + + /// + /// 投稿状态 + /// + public EPostStatus Status { get; set; } = EPostStatus.Unknown; + /// + /// 是否有附件 + /// + [SugarColumn(IsIgnore = true)] + public bool HasAttachments => PostType != MessageType.Text; + /// + /// 消息类型 + /// + public MessageType PostType { get; set; } = MessageType.Unknown; + /// + /// 是否为媒体组消息 + /// + [SugarColumn(IsIgnore = true)] + public bool IsMediaGroup => !string.IsNullOrEmpty(OriginMediaGroupID); + /// + /// 原始媒体组ID + /// + public string OriginMediaGroupID { get; set; } = ""; + /// + /// 审核消息媒体组ID + /// + public string ReviewMediaGroupID { get; set; } = ""; + /// + /// 发布频道或者拒绝频道的媒体组ID + /// + public string PublishMediaGroupID { get; set; } = ""; + /// + /// 稿件标签 + /// + public int Tags { get; set; } + /// + /// 是否启用遮罩 + /// + public bool HasSpoiler { get; set; } + /// + /// 是否允许遮罩 + /// + [SugarColumn(IsIgnore = true)] + public bool CanSpoiler => PostType == MessageType.Photo || PostType == MessageType.Video; + + /// + /// 拒绝原因(如果拒绝) + /// + public string RejectReason { get; set; } = ""; + /// + /// 拒绝理由计数 + /// + public bool CountReject { get; set; } + + /// + /// 投稿人用户ID + /// + public long PosterUID { get; set; } = -1; + /// + /// 审核人用户ID + /// + public long ReviewerUID { get; set; } = -1; + + /// + public DateTime CreateAt { get; set; } = DateTime.Now; + /// + public DateTime ModifyAt { get; set; } = DateTime.Now; + } +} diff --git a/XinjingdailyBot.Model/Models/Posts.cs b/XinjingdailyBot.Model/Models/OldPosts.cs similarity index 92% rename from XinjingdailyBot.Model/Models/Posts.cs rename to XinjingdailyBot.Model/Models/OldPosts.cs index 0215cc6c..b8ca2045 100644 --- a/XinjingdailyBot.Model/Models/Posts.cs +++ b/XinjingdailyBot.Model/Models/OldPosts.cs @@ -5,6 +5,7 @@ namespace XinjingdailyBot.Model.Models { + [Obsolete("弃用表")] [SugarTable("post", TableDescription = "投稿记录")] [SugarIndex("index_origin_cid", nameof(OriginChatID), OrderByType.Asc)] [SugarIndex("index_origin_mid", nameof(OriginMsgID), OrderByType.Asc)] @@ -16,7 +17,7 @@ namespace XinjingdailyBot.Model.Models [SugarIndex("index_posterid", nameof(PosterUID), OrderByType.Asc)] [SugarIndex("index_reviewerid", nameof(ReviewerUID), OrderByType.Asc)] [SugarIndex("index_status_modifyat", nameof(Status), OrderByType.Asc, nameof(ModifyAt), OrderByType.Asc)] - public sealed record Posts : BaseModel + public sealed record OldPosts : BaseModel { [SugarColumn(IsPrimaryKey = true, IsIdentity = true)] public int Id { get; set; } @@ -85,7 +86,7 @@ public sealed record Posts : BaseModel /// /// 投稿状态 /// - public PostStatus Status { get; set; } = PostStatus.Unknown; + public EPostStatus Status { get; set; } = EPostStatus.Unknown; /// /// 是否有附件 /// @@ -108,7 +109,7 @@ public sealed record Posts : BaseModel /// 标签 /// [Obsolete("过时的属性")] - public BuildInTags Tags { get; set; } + public EBuildInTags Tags { get; set; } /// /// 稿件标签 /// @@ -125,7 +126,7 @@ public sealed record Posts : BaseModel /// /// 拒绝原因(如果拒绝) /// - public RejectReason Reason { get; set; } = RejectReason.NotReject; + public ERejectReason Reason { get; set; } = ERejectReason.NotReject; /// /// 创建时间 /// @@ -142,5 +143,10 @@ public sealed record Posts : BaseModel /// 审核人用户ID /// public long ReviewerUID { get; set; } = -1; + + /// + /// 是否已完成迁移 + /// + public bool Merged { get; set; } } } diff --git a/XinjingdailyBot.Model/Models/RejectReasons.cs b/XinjingdailyBot.Model/Models/RejectReasons.cs new file mode 100644 index 00000000..ca79791a --- /dev/null +++ b/XinjingdailyBot.Model/Models/RejectReasons.cs @@ -0,0 +1,33 @@ +using SqlSugar; +using XinjingdailyBot.Model.Base; + +namespace XinjingdailyBot.Model.Models +{ + [SugarTable("reject", TableDescription = "拒绝理由")] + [SugarIndex("payload", nameof(Payload), OrderByType.Asc, true)] + public sealed record RejectReasons : BaseModel + { + [SugarColumn(IsPrimaryKey = true)] + public int Id { get; set; } = -1; + + /// + /// 显示名称 + /// + public string Name { get; set; } = ""; + + /// + /// CallbackData + /// + public string Payload { get; set; } = ""; + + /// + /// 发给用户的拒绝理由 + /// + public string FullText { get; set; } = ""; + + /// + /// 是否计入每日投稿上限计数 + /// + public bool IsCount { get; set; } = true; + } +} diff --git a/XinjingdailyBot.Model/Models/Tags.cs b/XinjingdailyBot.Model/Models/Tags.cs index 163f8b0d..942a78ec 100644 --- a/XinjingdailyBot.Model/Models/Tags.cs +++ b/XinjingdailyBot.Model/Models/Tags.cs @@ -4,8 +4,7 @@ namespace XinjingdailyBot.Model.Models { [SugarTable("tag", TableDescription = "投稿标签")] - [SugarIndex("index_name", nameof(Name), OrderByType.Asc, true)] - [SugarIndex("index_payload", nameof(Payload), OrderByType.Asc, true)] + [SugarIndex("payload", nameof(Payload), OrderByType.Asc, true)] public sealed record Tags : BaseModel { [SugarColumn(IsPrimaryKey = true)] diff --git a/XinjingdailyBot.Model/Models/UserToken.cs b/XinjingdailyBot.Model/Models/UserToken.cs new file mode 100644 index 00000000..1d8b2063 --- /dev/null +++ b/XinjingdailyBot.Model/Models/UserToken.cs @@ -0,0 +1,34 @@ +using SqlSugar; +using XinjingdailyBot.Model.Base; +using XinjingdailyBot.Model.Columns; + +namespace XinjingdailyBot.Model.Models +{ + /// + /// 用户密钥表, 储存WebAPI的Token + /// + [SugarTable("user_token", TableDescription = "用户密钥表")] + [SugarIndex("index_token", nameof(APIToken), OrderByType.Asc, false)] + public sealed record UserToken : BaseModel, ICreateAt, IExpiredAt + { + [SugarColumn(IsPrimaryKey = true)] + /// + /// 用户ID + /// + public long UserID { get; set; } + + /// + /// API Token + /// + public Guid APIToken { get; set; } + + /// + /// 创建时间 + /// + public DateTime CreateAt { get; set; } = DateTime.Now; + /// + /// 修改时间 + /// + public DateTime ExpiredAt { get; set; } = DateTime.MaxValue; + } +} diff --git a/XinjingdailyBot.Model/Models/Users.cs b/XinjingdailyBot.Model/Models/Users.cs index 3231d9ea..cc813b31 100644 --- a/XinjingdailyBot.Model/Models/Users.cs +++ b/XinjingdailyBot.Model/Models/Users.cs @@ -89,7 +89,7 @@ public sealed record Users : BaseModel /// 用户权限 /// [SugarColumn(IsIgnore = true)] - public UserRights Right { get; set; } = UserRights.None; + public EUserRights Right { get; set; } = EUserRights.None; /// /// 用户组ID /// diff --git a/XinjingdailyBot.Model/XinjingdailyBot.Model.csproj b/XinjingdailyBot.Model/XinjingdailyBot.Model.csproj index d5405815..899d112e 100644 --- a/XinjingdailyBot.Model/XinjingdailyBot.Model.csproj +++ b/XinjingdailyBot.Model/XinjingdailyBot.Model.csproj @@ -1,15 +1,19 @@  - - Library - + + Library + - - - + + + - - - + + + + + + + diff --git a/XinjingdailyBot.Repository/Base/BaseRepository.cs b/XinjingdailyBot.Repository/Base/BaseRepository.cs index 73595cb4..c0d2b1c5 100644 --- a/XinjingdailyBot.Repository/Base/BaseRepository.cs +++ b/XinjingdailyBot.Repository/Base/BaseRepository.cs @@ -1,7 +1,7 @@ -using System.Data; -using System.Linq.Expressions; -using SqlSugar; +using SqlSugar; using SqlSugar.IOC; +using System.Data; +using System.Linq.Expressions; using XinjingdailyBot.Model.Base; namespace XinjingdailyBot.Repository.Base diff --git a/XinjingdailyBot.Repository/Base/IBaseRepository.cs b/XinjingdailyBot.Repository/Base/IBaseRepository.cs index 6c59319b..0a66463c 100644 --- a/XinjingdailyBot.Repository/Base/IBaseRepository.cs +++ b/XinjingdailyBot.Repository/Base/IBaseRepository.cs @@ -1,6 +1,6 @@ -using System.Data; +using SqlSugar; +using System.Data; using System.Linq.Expressions; -using SqlSugar; using XinjingdailyBot.Model.Base; namespace XinjingdailyBot.Repository.Base diff --git a/XinjingdailyBot.Repository/GroupRepository.cs b/XinjingdailyBot.Repository/GroupRepository.cs index 3918deb0..802417aa 100644 --- a/XinjingdailyBot.Repository/GroupRepository.cs +++ b/XinjingdailyBot.Repository/GroupRepository.cs @@ -55,15 +55,15 @@ public async Task InitGroupCache() private async Task InsertBuildInGroups() { //请不要修改ID为0和1的字段 - List groups = new() + var groups = new List() { - new() { Id = 0, Name = "封禁用户", DefaultRight = UserRights.None }, - new() { Id = 1, Name = "普通用户", DefaultRight = UserRights.SendPost | UserRights.NormalCmd }, - new() { Id = 10, Name = "审核员", DefaultRight = UserRights.SendPost | UserRights.ReviewPost | UserRights.NormalCmd }, - new() { Id = 11, Name = "发布员", DefaultRight = UserRights.SendPost | UserRights.DirectPost | UserRights.NormalCmd }, - new() { Id = 20, Name = "狗管理", DefaultRight = UserRights.SendPost | UserRights.ReviewPost | UserRights.DirectPost | UserRights.NormalCmd | UserRights.AdminCmd }, - new() { Id = 30, Name = "超级狗管理", DefaultRight = UserRights.ALL }, - new() { Id = 50, Name = "*超级狗管理*", DefaultRight = UserRights.ALL }, + new() { Id = 0, Name = "封禁用户", DefaultRight = EUserRights.None }, + new() { Id = 1, Name = "普通用户", DefaultRight = EUserRights.SendPost | EUserRights.NormalCmd }, + new() { Id = 10, Name = "审核员", DefaultRight = EUserRights.SendPost | EUserRights.ReviewPost | EUserRights.NormalCmd }, + new() { Id = 11, Name = "发布员", DefaultRight = EUserRights.SendPost | EUserRights.DirectPost | EUserRights.NormalCmd }, + new() { Id = 20, Name = "狗管理", DefaultRight = EUserRights.SendPost | EUserRights.ReviewPost | EUserRights.DirectPost | EUserRights.NormalCmd | EUserRights.AdminCmd }, + new() { Id = 30, Name = "超级狗管理", DefaultRight = EUserRights.ALL }, + new() { Id = 50, Name = "*超级狗管理*", DefaultRight = EUserRights.ALL }, }; await Storageable(groups).ExecuteCommandAsync(); diff --git a/XinjingdailyBot.Repository/LevelRepository.cs b/XinjingdailyBot.Repository/LevelRepository.cs index 8fe8a17b..f20ff7b0 100644 --- a/XinjingdailyBot.Repository/LevelRepository.cs +++ b/XinjingdailyBot.Repository/LevelRepository.cs @@ -8,14 +8,14 @@ namespace XinjingdailyBot.Repository [AppService(LifeTime.Singleton)] public class LevelRepository : BaseRepository { - private readonly ILogger _logger; + private readonly ILogger _logger; - public LevelRepository(ILogger logger) + public LevelRepository(ILogger logger) { _logger = logger; } - private readonly Dictionary _levelCache = new(); + private Dictionary _levelCache { get; } = new(); /// /// 初始化缓存 @@ -54,7 +54,7 @@ public async Task InitLevelCache() private async Task InsertBuildInLevels() { //请不要修改ID为0和1的字段 - List levels = new() + var levels = new List() { new() { Id = 0, Name = "Lv-" }, new() { Id = 1, Name = "Lv0", MinExp = 0, MaxExp = 10 }, diff --git a/XinjingdailyBot.Repository/OldPostRepository.cs b/XinjingdailyBot.Repository/OldPostRepository.cs new file mode 100644 index 00000000..50324754 --- /dev/null +++ b/XinjingdailyBot.Repository/OldPostRepository.cs @@ -0,0 +1,12 @@ +using XinjingdailyBot.Infrastructure.Attribute; +using XinjingdailyBot.Model.Models; +using XinjingdailyBot.Repository.Base; + +namespace XinjingdailyBot.Repository +{ + [AppService(LifeTime.Transient)] + [Obsolete("废弃的仓储类")] + public class OldPostRepository : BaseRepository + { + } +} diff --git a/XinjingdailyBot.Repository/PostRepository.cs b/XinjingdailyBot.Repository/PostRepository.cs index 84fe681d..48071cfb 100644 --- a/XinjingdailyBot.Repository/PostRepository.cs +++ b/XinjingdailyBot.Repository/PostRepository.cs @@ -5,7 +5,7 @@ namespace XinjingdailyBot.Repository { [AppService(LifeTime.Transient)] - public class PostRepository : BaseRepository + public class PostRepository : BaseRepository { } } diff --git a/XinjingdailyBot.Repository/RejectReasonRepository.cs b/XinjingdailyBot.Repository/RejectReasonRepository.cs new file mode 100644 index 00000000..9660c57c --- /dev/null +++ b/XinjingdailyBot.Repository/RejectReasonRepository.cs @@ -0,0 +1,138 @@ +using Microsoft.Extensions.Logging; +using XinjingdailyBot.Infrastructure.Attribute; +using XinjingdailyBot.Model.Models; +using XinjingdailyBot.Repository.Base; + +namespace XinjingdailyBot.Repository +{ + [AppService(LifeTime.Singleton)] + public class RejectReasonRepository : BaseRepository + { + private readonly ILogger _logger; + + public RejectReasonRepository(ILogger logger) + { + _logger = logger; + } + + /// + /// 拒绝理由缓存, Key=Id + /// + private Dictionary RejectReasonCache { get; } = new(); + /// + /// 标签缓存, Key=Payload + /// + private Dictionary RejectReasonPayloadCache { get; } = new(); + + /// + /// 初始化缓存 + /// + /// + public async Task InitRejectReasonCache() + { + var reasonCount = await CountAsync(x => true); + if (reasonCount == 0) + { + _logger.LogInformation("未设置拒绝理由,正在创建内置拒绝理由"); + await InsertBuildInRejectReasons(); + } + + var reasons = await GetListAsync(); + if (reasons?.Count > 0) + { + RejectReasonCache.Clear(); + RejectReasonPayloadCache.Clear(); + + bool changed = false; + + foreach (var reason in reasons) + { + if (string.IsNullOrEmpty(reason.Name) || reason.Id <= 0) + { + continue; + } + + if (string.IsNullOrEmpty(reason.Payload)) + { + reason.Payload = reason.Name; + changed = true; + } + reason.Payload = reason.Payload.ToLowerInvariant(); + + RejectReasonCache.Add(reason.Id, reason); + RejectReasonPayloadCache.Add(reason.Payload, reason); + } + + if (changed) + { + await Storageable(reasons).ExecuteCommandAsync(); + } + + _logger.LogInformation("已加载 {Count} 个拒绝理由", reasons.Count); + } + else + { + _logger.LogError("意外错误, 拒绝理由数据为空"); + Environment.Exit(1); + } + } + + /// + /// 创建内置拒绝理由 + /// + /// + private async Task InsertBuildInRejectReasons() + { + var levels = new List() + { + new() { Id = 1, Name = "模糊", Payload = "fuzzy", FullText = "图片模糊/看不清", IsCount = false }, + new() { Id = 2, Name = "重复", Payload = "duplicate", FullText = "重复的稿件", IsCount = false }, + new() { Id = 3, Name = "无趣", Payload = "boring", FullText = "内容不够有趣" }, + new() { Id = 4, Name = "没懂", Payload = "confusing", FullText = "审核没看懂,建议配文说明" }, + new() { Id = 5, Name = "不合适", Payload = "deny", FullText = "不合适发布的内容" }, + new() { Id = 6, Name = "广告水印", Payload = "qrcode", FullText = "稿件包含二维码水印" }, + new() { Id = 7, Name = "其他原因", Payload = "other", FullText = "其他原因" }, + new() { Id = 8, Name = "太多了", Payload = "toomuch", FullText = "今天此类型的稿件的数量太多了" }, + }; + + await Storageable(levels).ExecuteCommandAsync(); + } + + /// + /// 根据Id获取拒绝理由 + /// + /// + /// + public RejectReasons? GetReasonById(int reasonId) + { + if (RejectReasonCache.TryGetValue(reasonId, out var level)) + { + return level; + } + return null; + } + + /// + /// 根据Payload获取拒绝理由 + /// + /// + /// + public RejectReasons? GetReasonByPayload(string payload) + { + if (RejectReasonPayloadCache.TryGetValue(payload, out var reason)) + { + return reason; + } + return null; + } + + /// + /// 获取所有拒绝理由 + /// + /// + public IEnumerable GetAllRejectReasons() + { + return RejectReasonCache.Values; + } + } +} diff --git a/XinjingdailyBot.Repository/TagRepository.cs b/XinjingdailyBot.Repository/TagRepository.cs index fbaff3f0..7e6b447a 100644 --- a/XinjingdailyBot.Repository/TagRepository.cs +++ b/XinjingdailyBot.Repository/TagRepository.cs @@ -19,15 +19,19 @@ public TagRepository(ILogger logger) /// /// 标签缓存, Key=Id /// - private readonly Dictionary _tagCache = new(); + private Dictionary TagCache { get; } = new(); + /// + /// 标签缓存, Key=Payload + /// + private Dictionary TagPayloadCache { get; } = new(); /// /// 标签缓存, Key=Id /// - private readonly Dictionary _tagKeywords = new(); + private Dictionary TagKeywords { get; } = new(); /// /// 警告文本缓存 /// - private readonly List _warnTexts = new(); + private List WarnTexts { get; } = new(); /// /// 初始化缓存 @@ -45,9 +49,13 @@ public async Task InitPostTagCache() var tags = await GetListAsync(x => x.Id > 0 && x.Id < 32); if (tags?.Count > 0) { - _tagCache.Clear(); - _tagKeywords.Clear(); - _warnTexts.Clear(); + TagCache.Clear(); + TagPayloadCache.Clear(); + TagKeywords.Clear(); + WarnTexts.Clear(); + + bool changed = false; + foreach (var tag in tags) { if (string.IsNullOrEmpty(tag.Name) || tag.Id <= 0) @@ -58,40 +66,49 @@ public async Task InitPostTagCache() if (string.IsNullOrEmpty(tag.Payload)) { tag.Payload = tag.Name; + changed = true; } if (string.IsNullOrEmpty(tag.OnText)) { tag.OnText = "#" + tag.Name; + changed = true; } if (string.IsNullOrEmpty(tag.OffText)) { tag.OffText = "#" + tag.Name.First() + new string('_', tag.Name.Length - 1); + changed = true; } if (string.IsNullOrEmpty(tag.HashTag)) { tag.HashTag = "#" + tag.Name; + changed = true; } tag.Payload = tag.Payload.ToLowerInvariant(); tag.Seg = 1 << tag.Id - 1; - _tagCache.Add(tag.Id, tag); + + TagCache.Add(tag.Id, tag); + TagPayloadCache.Add(tag.Payload, tag); if (!string.IsNullOrEmpty(tag.KeyWords)) { var keyWords = tag.KeyWords.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries); if (keyWords?.Length > 0) { - _tagKeywords.Add(tag.Seg, keyWords); + TagKeywords.Add(tag.Seg, keyWords); } } if (!string.IsNullOrEmpty(tag.WarnText)) { - _warnTexts.Add(tag.WarnText); + WarnTexts.Add(tag.WarnText); } } - await Storageable(tags).ExecuteCommandAsync(); + if (changed) + { + await Storageable(tags).ExecuteCommandAsync(); + } _logger.LogInformation("已加载 {Count} 个标签", tags.Count); } @@ -110,10 +127,10 @@ private async Task InsertBuildInTags() { List tags = new() { - new() { Id = 1,Name = "NSFW", Payload = "nsfw", KeyWords = "NSFW", WarnText = Langs.NSFWWarning }, - new() { Id = 2,Name = "我有一个朋友", Payload = "friend", KeyWords = "朋友|英雄" }, - new() { Id = 3,Name = "晚安", Payload = "wanan", KeyWords = "晚安" }, - new() { Id = 4,Name = "AI怪图", Payload = "ai", KeyWords = "#AI" }, + new() { Id = 1, Name = "NSFW", Payload = "nsfw", KeyWords = "NSFW", WarnText = Langs.NSFWWarning }, + new() { Id = 2, Name = "我有一个朋友", Payload = "friend", KeyWords = "朋友|英雄" }, + new() { Id = 3, Name = "晚安", Payload = "wanan", KeyWords = "晚安" }, + new() { Id = 4, Name = "AI怪图", Payload = "ai", KeyWords = "#AI" }, }; await Storageable(tags).ExecuteCommandAsync(); @@ -126,7 +143,7 @@ private async Task InsertBuildInTags() /// public Tags? GetTagById(int tagId) { - if (_tagCache.TryGetValue(tagId, out var tag)) + if (TagCache.TryGetValue(tagId, out var tag)) { return tag; } @@ -140,12 +157,9 @@ private async Task InsertBuildInTags() /// public Tags? GetTagByPayload(string payload) { - foreach (var tag in _tagCache.Values) + if (TagPayloadCache.TryGetValue(payload, out var tag)) { - if (tag.Payload == payload) - { - return tag; - } + return tag; } return null; } @@ -156,7 +170,7 @@ private async Task InsertBuildInTags() /// public IEnumerable GetAllTags() { - return _tagCache.Values; + return TagCache.Values; } /// @@ -166,12 +180,12 @@ public IEnumerable GetAllTags() /// public int FetchTags(string? text) { - if (string.IsNullOrEmpty(text) || _tagCache.Count == 0) + if (string.IsNullOrEmpty(text) || TagCache.Count == 0) { return 0; } int tagNum = 0; - foreach (var (seg, words) in _tagKeywords) + foreach (var (seg, words) in TagKeywords) { foreach (var word in words) { @@ -193,7 +207,7 @@ public int FetchTags(string? text) public IEnumerable GetActiviedTags(int tagNum) { List tags = new(); - foreach (var tag in _tagCache.Values) + foreach (var tag in TagCache.Values) { if ((tag.Seg & tagNum) > 0) { @@ -256,7 +270,7 @@ public int GetActiviedTagsCounte(int tagNum) public IEnumerable GetTagsPayload(int tagNum) { List tags = new(); - foreach (var tag in _tagCache.Values) + foreach (var tag in TagCache.Values) { bool status = (tag.Seg & tagNum) > 0; @@ -281,7 +295,7 @@ public bool IsWarnText(string? text) { text = text.Split(new[] { '\n' }, StringSplitOptions.RemoveEmptyEntries).First(); } - bool result = _warnTexts.Any(x => x == text); + bool result = WarnTexts.Any(x => x == text); return result; } } diff --git a/XinjingdailyBot.Repository/XinjingdailyBot.Repository.csproj b/XinjingdailyBot.Repository/XinjingdailyBot.Repository.csproj index 844e6fa5..93fa2cf3 100644 --- a/XinjingdailyBot.Repository/XinjingdailyBot.Repository.csproj +++ b/XinjingdailyBot.Repository/XinjingdailyBot.Repository.csproj @@ -1,16 +1,20 @@  - - Library - + + Library + - - - + + + - - - - + + + + + + + + diff --git a/XinjingdailyBot.Service/Bot/Common/ChannelService.cs b/XinjingdailyBot.Service/Bot/Common/ChannelService.cs index 4c04d926..686cbe0f 100644 --- a/XinjingdailyBot.Service/Bot/Common/ChannelService.cs +++ b/XinjingdailyBot.Service/Bot/Common/ChannelService.cs @@ -144,10 +144,18 @@ public bool IsChannelMessage(long chatId) { return chatId == _acceptChannel.Id || chatId == _rejectChannel.Id; } + public bool IsChannelMessage(Chat chat) + { + return chat.Id == _acceptChannel.Id || chat.Id == _rejectChannel.Id; + } public bool IsGroupMessage(long chatId) { return chatId == _subGroup.Id || chatId == _commentGroup.Id; } + public bool IsGroupMessage(Chat chat) + { + return chat.Id == _subGroup.Id || chat.Id == _commentGroup.Id; + } } } diff --git a/XinjingdailyBot.Service/Bot/Common/DispatcherService.cs b/XinjingdailyBot.Service/Bot/Common/DispatcherService.cs index a84e3530..4a05923e 100644 --- a/XinjingdailyBot.Service/Bot/Common/DispatcherService.cs +++ b/XinjingdailyBot.Service/Bot/Common/DispatcherService.cs @@ -109,8 +109,7 @@ public async Task OnChannalPostReceived(Users dbUser, Message message) //仅监听发布频道的消息 if (message.Chat.Id == _channelService.AcceptChannel.Id) { - var handler = message.Type switch - { + var handler = message.Type switch { MessageType.Text => _channelPostHandler.OnTextChannelPostReceived(dbUser, message), MessageType.Photo => _channelPostHandler.OnMediaChannelPostReceived(dbUser, message), MessageType.Audio => _channelPostHandler.OnMediaChannelPostReceived(dbUser, message), diff --git a/XinjingdailyBot.Service/Bot/Common/PollingService.cs b/XinjingdailyBot.Service/Bot/Common/PollingService.cs index a31ef998..2ebd389f 100644 --- a/XinjingdailyBot.Service/Bot/Common/PollingService.cs +++ b/XinjingdailyBot.Service/Bot/Common/PollingService.cs @@ -1,7 +1,7 @@ -using System.Diagnostics.CodeAnalysis; -using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; +using System.Diagnostics.CodeAnalysis; using XinjingdailyBot.Interface.Bot.Common; using XinjingdailyBot.Interface.Bot.Handler; using XinjingdailyBot.Repository; @@ -20,6 +20,7 @@ public class PollingService : BackgroundService private readonly GroupRepository _groupRepository; private readonly LevelRepository _levelRepository; private readonly TagRepository _tagRepository; + private readonly RejectReasonRepository _rejectReasonRepository; public PollingService( IServiceProvider serviceProvider, @@ -28,7 +29,8 @@ public PollingService( ICommandHandler commandHandler, GroupRepository groupRepository, LevelRepository levelRepository, - TagRepository tagRepository) + TagRepository tagRepository, + RejectReasonRepository rejectReasonRepository) { _serviceProvider = serviceProvider; _logger = logger; @@ -37,6 +39,7 @@ public PollingService( _groupRepository = groupRepository; _levelRepository = levelRepository; _tagRepository = tagRepository; + _rejectReasonRepository = rejectReasonRepository; } [RequiresUnreferencedCode("不兼容剪裁")] @@ -52,6 +55,7 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken) await _groupRepository.InitGroupCache(); await _levelRepository.InitLevelCache(); await _tagRepository.InitPostTagCache(); + await _rejectReasonRepository.InitRejectReasonCache(); _logger.LogInformation("开始运行 Bot"); await DoWork(stoppingToken); diff --git a/XinjingdailyBot.Service/Bot/Common/ReceiverService.cs b/XinjingdailyBot.Service/Bot/Common/ReceiverService.cs index e4879554..6cffab25 100644 --- a/XinjingdailyBot.Service/Bot/Common/ReceiverService.cs +++ b/XinjingdailyBot.Service/Bot/Common/ReceiverService.cs @@ -31,8 +31,7 @@ public ReceiverService( public async Task ReceiveAsync(CancellationToken stoppingToken) { - ReceiverOptions receiverOptions = new() - { + ReceiverOptions receiverOptions = new() { AllowedUpdates = Array.Empty(), ThrowPendingUpdates = true || _optionsSetting.Bot.ThrowPendingUpdates, }; diff --git a/XinjingdailyBot.Service/Bot/Common/UpdateService.cs b/XinjingdailyBot.Service/Bot/Common/UpdateService.cs index e1e90319..1c120c43 100644 --- a/XinjingdailyBot.Service/Bot/Common/UpdateService.cs +++ b/XinjingdailyBot.Service/Bot/Common/UpdateService.cs @@ -39,8 +39,7 @@ public async Task HandleUpdateAsync(ITelegramBotClient _, Update update, Cancell return; } - var handler = update.Type switch - { + var handler = update.Type switch { UpdateType.ChannelPost => _dispatcherService.OnChannalPostReceived(dbUser, update.ChannelPost!), UpdateType.Message => _dispatcherService.OnMessageReceived(dbUser, update.Message!), UpdateType.CallbackQuery => _dispatcherService.OnCallbackQueryReceived(dbUser, update.CallbackQuery!), @@ -57,8 +56,7 @@ public async Task HandleUpdateAsync(ITelegramBotClient _, Update update, Cancell public async Task HandlePollingErrorAsync(ITelegramBotClient _, Exception exception, CancellationToken cancellationToken) { - var ErrorMessage = exception switch - { + var ErrorMessage = exception switch { ApiRequestException apiRequestException => $"Telegram API Error:\n[{apiRequestException.ErrorCode}]\n{apiRequestException.Message}", _ => exception.ToString() }; diff --git a/XinjingdailyBot.Service/Bot/Handler/ChannelPostHandler.cs b/XinjingdailyBot.Service/Bot/Handler/ChannelPostHandler.cs index b76a249c..f58c851e 100644 --- a/XinjingdailyBot.Service/Bot/Handler/ChannelPostHandler.cs +++ b/XinjingdailyBot.Service/Bot/Handler/ChannelPostHandler.cs @@ -1,5 +1,5 @@ -using System.Collections.Concurrent; -using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging; +using System.Collections.Concurrent; using Telegram.Bot; using Telegram.Bot.Types; using Telegram.Bot.Types.Enums; @@ -10,13 +10,13 @@ using XinjingdailyBot.Interface.Helper; using XinjingdailyBot.Model.Models; using XinjingdailyBot.Repository; -using XinjingdailyBot.Service.Data; namespace XinjingdailyBot.Service.Bot.Handler { [AppService(typeof(IChannelPostHandler), LifeTime.Singleton)] public class ChannelPostHandler : IChannelPostHandler { + private readonly ILogger _logger; private readonly IPostService _postService; private readonly ITextHelperService _textHelperService; private readonly IAttachmentService _attachmentService; @@ -24,10 +24,10 @@ public class ChannelPostHandler : IChannelPostHandler private readonly IChannelOptionService _channelOptionService; private readonly TagRepository _tagRepository; private readonly ITelegramBotClient _botClient; - private readonly ILogger _logger; private readonly IMediaGroupService _mediaGroupService; public ChannelPostHandler( + ILogger logger, IPostService postService, ITextHelperService textHelperService, IAttachmentService attachmentService, @@ -35,9 +35,9 @@ public ChannelPostHandler( IChannelOptionService channelOptionService, TagRepository tagRepository, ITelegramBotClient botClient, - ILogger logger, IMediaGroupService mediaGroupService) { + _logger = logger; _postService = postService; _textHelperService = textHelperService; _attachmentService = attachmentService; @@ -45,7 +45,6 @@ public ChannelPostHandler( _channelOptionService = channelOptionService; _tagRepository = tagRepository; _botClient = botClient; - _logger = logger; _mediaGroupService = mediaGroupService; } @@ -60,42 +59,45 @@ public async Task OnTextChannelPostReceived(Users dbUser, Message message) return; } - string? channelName = null, channelTitle = null; + long channelId = -1, channelMsgId = -1; if (message.ForwardFromChat?.Type == ChatType.Channel) { - channelTitle = message.ForwardFromChat.Title; - channelName = $"{message.ForwardFromChat.Username}/{message.ForwardFromMessageId}"; - long channelId = message.ForwardFromChat.Id; - var option = await _channelOptionService.FetchChannelOption(channelId, message.ForwardFromChat.Username, channelTitle); + channelId = message.ForwardFromChat.Id; + channelMsgId = message.ForwardFromMessageId ?? -1; + + var option = await _channelOptionService.FetchChannelOption(message.ForwardFromChat); - if (option == ChannelOption.AutoReject) + if (option == EChannelOption.AutoReject) { await _botClient.DeleteMessageAsync(message.Chat, message.MessageId); _logger.LogInformation("删除消息 {msgid}", message.MessageId); return; } + } int newTag = _tagRepository.FetchTags(message.Text); string text = _textHelperService.ParseMessage(message); //生成数据库实体 - Posts newPost = new() - { + var newPost = new NewPosts { OriginChatID = message.Chat.Id, OriginMsgID = message.MessageId, - ActionMsgID = 0, + OriginActionChatID = 0, + OriginActionMsgID = 0, + ReviewChatID = 0, ReviewMsgID = 0, - ManageMsgID = 0, + ReviewActionChatID = 0, + ReviewActionMsgID = 0, PublicMsgID = message.MessageId, Anonymous = false, Text = text, RawText = message.Text ?? "", - ChannelName = channelName ?? "", - ChannelTitle = channelTitle ?? "", - Status = PostStatus.Accepted, + ChannelID = channelId, + ChannelMsgId = channelMsgId, + Status = EPostStatus.Accepted, PostType = message.Type, - NewTags = newTag, + Tags = newTag, PosterUID = dbUser.UserID, ReviewerUID = dbUser.UserID }; @@ -110,15 +112,14 @@ public async Task OnTextChannelPostReceived(Users dbUser, Message message) public async Task OnMediaChannelPostReceived(Users dbUser, Message message) { - string? channelName = null, channelTitle = null; + long channelId = -1, channelMsgId = -1; if (message.ForwardFromChat?.Type == ChatType.Channel) { - channelTitle = message.ForwardFromChat.Title; - channelName = $"{message.ForwardFromChat.Username}/{message.ForwardFromMessageId}"; - long channelId = message.ForwardFromChat.Id; - var option = await _channelOptionService.FetchChannelOption(channelId, message.ForwardFromChat.Username, channelTitle); + channelId = message.ForwardFromChat.Id; + channelMsgId = message.ForwardFromMessageId ?? -1; + var option = await _channelOptionService.FetchChannelOption(message.ForwardFromChat); - if (option == ChannelOption.AutoReject) + if (option == EChannelOption.AutoReject) { await _botClient.DeleteMessageAsync(message.Chat, message.MessageId); _logger.LogInformation("删除消息 {msgid}", message.MessageId); @@ -130,22 +131,24 @@ public async Task OnMediaChannelPostReceived(Users dbUser, Message message) string text = _textHelperService.ParseMessage(message); //生成数据库实体 - Posts newPost = new() - { + var newPost = new NewPosts { OriginChatID = message.Chat.Id, OriginMsgID = message.MessageId, - ActionMsgID = 0, + OriginActionChatID = 0, + OriginActionMsgID = 0, + ReviewChatID = 0, ReviewMsgID = 0, - ManageMsgID = 0, + ReviewActionChatID = 0, + ReviewActionMsgID = 0, PublicMsgID = message.MessageId, Anonymous = false, Text = text, RawText = message.Text ?? "", - ChannelName = channelName ?? "", - ChannelTitle = channelTitle ?? "", - Status = PostStatus.Accepted, + ChannelID = channelId, + ChannelMsgId = channelMsgId, + Status = EPostStatus.Accepted, PostType = message.Type, - NewTags = newTags, + Tags = newTags, HasSpoiler = message.HasMediaSpoiler ?? false, PosterUID = dbUser.UserID, ReviewerUID = dbUser.UserID @@ -178,18 +181,18 @@ public async Task OnMediaGroupChannelPostReceived(Users dbUser, Message message) { MediaGroupIDs.TryAdd(mediaGroupId, -1); - bool exists = await _postService.Queryable().AnyAsync(x => x.MediaGroupID == mediaGroupId); + bool exists = await _postService.Queryable().AnyAsync(x => x.OriginMediaGroupID == mediaGroupId); if (!exists) { - string? channelName = null, channelTitle = null; + long channelId = -1, channelMsgId = -1; if (message.ForwardFromChat?.Type == ChatType.Channel) { - channelTitle = message.ForwardFromChat.Title; - channelName = $"{message.ForwardFromChat.Username}/{message.ForwardFromMessageId}"; - long channelId = message.ForwardFromChat.Id; - var option = await _channelOptionService.FetchChannelOption(channelId, message.ForwardFromChat.Username, channelTitle); + channelId = message.ForwardFromChat.Id; + channelMsgId = message.ForwardFromMessageId ?? -1; - if (option == ChannelOption.AutoReject) + var option = await _channelOptionService.FetchChannelOption(message.ForwardFromChat); + + if (option == EChannelOption.AutoReject) { await _botClient.DeleteMessageAsync(message.Chat, message.MessageId); _logger.LogInformation("删除消息 {msgid}", message.MessageId); @@ -201,22 +204,25 @@ public async Task OnMediaGroupChannelPostReceived(Users dbUser, Message message) string text = _textHelperService.ParseMessage(message); //生成数据库实体 - Posts newPost = new() - { + var newPost = new NewPosts { OriginChatID = message.Chat.Id, OriginMsgID = message.MessageId, - ActionMsgID = 0, + OriginActionChatID = 0, + OriginActionMsgID = 0, + ReviewChatID = 0, ReviewMsgID = 0, - ManageMsgID = 0, + ReviewActionChatID = 0, + ReviewActionMsgID = 0, PublicMsgID = message.MessageId, + PublishMediaGroupID = mediaGroupId, Anonymous = false, Text = text, RawText = message.Text ?? "", - ChannelName = channelName ?? "", - ChannelTitle = channelTitle ?? "", - Status = PostStatus.Accepted, + ChannelID = channelId, + ChannelMsgId = channelMsgId, + Status = EPostStatus.Accepted, PostType = message.Type, - NewTags = newTags, + Tags = newTags, HasSpoiler = message.HasMediaSpoiler ?? false, PosterUID = dbUser.UserID, ReviewerUID = dbUser.UserID @@ -227,15 +233,17 @@ public async Task OnMediaGroupChannelPostReceived(Users dbUser, Message message) MediaGroupIDs[mediaGroupId] = postID; //两秒后停止接收媒体组消息 - _ = Task.Run(async () => - { + _ = Task.Run(async () => { await Task.Delay(1500); MediaGroupIDs.Remove(mediaGroupId, out _); //增加通过数量 dbUser.AcceptCount++; dbUser.ModifyAt = DateTime.Now; - await _userService.Updateable(dbUser).UpdateColumns(x => new { x.AcceptCount, x.ModifyAt }).ExecuteCommandAsync(); + await _userService.Updateable(dbUser).UpdateColumns(x => new { + x.AcceptCount, + x.ModifyAt + }).ExecuteCommandAsync(); }); } } diff --git a/XinjingdailyBot.Service/Bot/Handler/CommandHandler.cs b/XinjingdailyBot.Service/Bot/Handler/CommandHandler.cs index 88a88c49..7eac41e6 100644 --- a/XinjingdailyBot.Service/Bot/Handler/CommandHandler.cs +++ b/XinjingdailyBot.Service/Bot/Handler/CommandHandler.cs @@ -1,8 +1,8 @@ -using System.Diagnostics.CodeAnalysis; -using System.Reflection; -using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; +using System.Diagnostics.CodeAnalysis; +using System.Reflection; using Telegram.Bot; using Telegram.Bot.Types; using Telegram.Bot.Types.Enums; @@ -81,13 +81,13 @@ public void InstallCommands() /// 注册命令 /// /// - //[RequiresUnreferencedCode("不兼容剪裁")] + [RequiresUnreferencedCode("不兼容剪裁")] private void RegisterCommands([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] Type type) { - Dictionary commands = new(); - Dictionary commandAlias = new(); - Dictionary queryCommands = new(); - Dictionary queryAlias = new(); + var commands = new Dictionary(); + var commandAlias = new Dictionary(); + var queryCommands = new Dictionary(); + var queryAlias = new Dictionary(); foreach (var method in type.GetMethods()) { @@ -199,8 +199,7 @@ public async Task OnCommandReceived(Users dbUser, Message message) if (_channelService.IsGroupMessage(message.Chat.Id)) { //删除原消息 - _ = Task.Run(async () => - { + _ = Task.Run(async () => { await Task.Delay(TimeSpan.FromSeconds(30)); try { @@ -252,7 +251,7 @@ private async Task CallCommandAsync(Users dbUser, Message message, Type type, As //获取服务 var service = _serviceScope.ServiceProvider.GetRequiredService(type); var method = assemblyMethod.Method; - List methodParameters = new(); + var methodParameters = new List(); //组装函数的入参 foreach (var parameter in method.GetParameters()) { @@ -384,7 +383,7 @@ private async Task CallQueryCommandAsync(Users dbUser, CallbackQuery query, Type //获取服务 var service = _serviceScope.ServiceProvider.GetRequiredService(type); var method = assemblyMethod.Method; - List methodParameters = new(); + var methodParameters = new List(); //组装函数的入参 foreach (var parameter in method.GetParameters()) { @@ -414,7 +413,7 @@ private async Task CallQueryCommandAsync(Users dbUser, CallbackQuery query, Type public string GetAvilabeCommands(Users dbUser) { - Dictionary cmds = new(); + var cmds = new Dictionary(); foreach (var type in _commandClass.Keys) { @@ -445,9 +444,9 @@ public string GetAvilabeCommands(Users dbUser) public async Task GetCommandsMenu() { - List cmds = new(); + var cmds = new List(); - void AddCommands(UserRights right) + void AddCommands(EUserRights right) { foreach (var type in _commandClass.Keys) { @@ -466,15 +465,15 @@ void AddCommands(UserRights right) } } - AddCommands(UserRights.None); - AddCommands(UserRights.NormalCmd); + AddCommands(EUserRights.None); + AddCommands(EUserRights.NormalCmd); await _botClient.SetMyCommandsAsync(cmds, new BotCommandScopeAllPrivateChats()); await _botClient.SetMyCommandsAsync(cmds, new BotCommandScopeAllGroupChats()); - AddCommands(UserRights.AdminCmd); + AddCommands(EUserRights.AdminCmd); await _botClient.SetMyCommandsAsync(cmds, new BotCommandScopeAllChatAdministrators()); - AddCommands(UserRights.ReviewPost); + AddCommands(EUserRights.ReviewPost); await _botClient.SetMyCommandsAsync(cmds, new BotCommandScopeChatAdministrators { ChatId = _channelService.ReviewGroup.Id }); return true; } diff --git a/XinjingdailyBot.Service/Bot/Handler/ForwardMessageHandler.cs b/XinjingdailyBot.Service/Bot/Handler/ForwardMessageHandler.cs index 0810e2b2..e510e2a3 100644 --- a/XinjingdailyBot.Service/Bot/Handler/ForwardMessageHandler.cs +++ b/XinjingdailyBot.Service/Bot/Handler/ForwardMessageHandler.cs @@ -1,25 +1,21 @@ using System.Text; -using Microsoft.Extensions.Logging; using Telegram.Bot; using Telegram.Bot.Types; using Telegram.Bot.Types.Enums; using XinjingdailyBot.Infrastructure.Attribute; using XinjingdailyBot.Infrastructure.Enums; using XinjingdailyBot.Infrastructure.Extensions; -using XinjingdailyBot.Infrastructure.Localization; using XinjingdailyBot.Interface.Bot.Common; using XinjingdailyBot.Interface.Bot.Handler; using XinjingdailyBot.Interface.Data; using XinjingdailyBot.Interface.Helper; using XinjingdailyBot.Model.Models; -using XinjingdailyBot.Service.Bot.Common; namespace XinjingdailyBot.Service.Bot.Handler { [AppService(typeof(IForwardMessageHandler), LifeTime.Singleton)] public class ForwardMessageHandler : IForwardMessageHandler { - private readonly ILogger _logger; private readonly IChannelService _channelService; private readonly ITelegramBotClient _botClient; private readonly IPostService _postService; @@ -28,7 +24,6 @@ public class ForwardMessageHandler : IForwardMessageHandler private readonly IMediaGroupService _mediaGroupService; public ForwardMessageHandler( - ILogger logger, ITelegramBotClient botClient, IChannelService channelService, IPostService postService, @@ -36,7 +31,6 @@ public ForwardMessageHandler( IUserService userService, IMediaGroupService mediaGroupService) { - _logger = logger; _botClient = botClient; _channelService = channelService; _postService = postService; @@ -47,41 +41,41 @@ public ForwardMessageHandler( public async Task OnForwardMessageReceived(Users dbUser, Message message) { - if (dbUser.Right.HasFlag(UserRights.AdminCmd)) + if (dbUser.Right.HasFlag(EUserRights.AdminCmd)) { var forwardFrom = message.ForwardFrom!; - var forwardFromChat = message.ForwardFromChat; - var foreardMsgId = message.ForwardFromMessageId; + var forwardChatId = message.ForwardFromChat?.Id ?? -1; + var foreardMsgId = message.ForwardFromMessageId ?? -1; - if (forwardFromChat != null && foreardMsgId != null - && (_channelService.IsChannelMessage(forwardFromChat.Id) || _channelService.IsGroupMessage(forwardFromChat.Id))) + if (forwardChatId != -1 && foreardMsgId != -1 && + (_channelService.IsChannelMessage(forwardChatId) || _channelService.IsGroupMessage(forwardChatId))) { - Posts? post = null; + NewPosts? post = null; - bool isMediaGroup = !string.IsNullOrEmpty(message.MediaGroupId); - if (!isMediaGroup) + var mediaGroup = await _mediaGroupService.QueryMediaGroup(forwardChatId, foreardMsgId); + if (mediaGroup == null) { - if (forwardFromChat.Id == _channelService.AcceptChannel.Id) + if (_channelService.IsChannelMessage(forwardChatId)) //转发自发布频道或拒绝存档 { post = await _postService.GetFirstAsync(x => x.PublicMsgID == foreardMsgId); } - else if (forwardFromChat.Id == _channelService.ReviewGroup.Id) + else //转发自关联群组 { - post = await _postService.GetFirstAsync(x => x.ReviewMsgID == foreardMsgId || x.ManageMsgID == foreardMsgId); + post = await _postService.GetFirstAsync(x => + (x.ReviewChatID == forwardChatId && x.ReviewMsgID == foreardMsgId) || + (x.ReviewActionChatID == forwardChatId && x.ReviewActionMsgID == foreardMsgId) + ); } } else { - var groupMsgs = await _mediaGroupService.QueryMediaGroup(message.MediaGroupId); - var msgIds = groupMsgs.Select(x => x.MessageID).ToList(); - - if (forwardFromChat.Id == _channelService.AcceptChannel.Id) + if (_channelService.IsChannelMessage(forwardChatId)) //转发自发布频道或拒绝存档 { - post = await _postService.GetFirstAsync(x => msgIds.Contains(x.PublicMsgID)); + post = await _postService.GetFirstAsync(x => x.PublishMediaGroupID == mediaGroup.MediaGroupID); } - else if (forwardFromChat.Id == _channelService.ReviewGroup.Id) + else //转发自关联群组 (仅支持审核群) { - post = await _postService.GetFirstAsync(x => msgIds.Contains(x.ReviewMsgID) || msgIds.Contains(x.ManageMsgID)); + post = await _postService.GetFirstAsync(x => x.ReviewMediaGroupID == mediaGroup.MediaGroupID); } } @@ -90,7 +84,7 @@ public async Task OnForwardMessageReceived(Users dbUser, Message message) var poster = await _userService.FetchUserByUserID(post.PosterUID); if (poster != null) { - if (post.Status == PostStatus.Reviewing) + if (post.Status == EPostStatus.Reviewing) { await _botClient.AutoReplyAsync("无法操作审核中的稿件", message); return false; @@ -98,12 +92,11 @@ public async Task OnForwardMessageReceived(Users dbUser, Message message) var keyboard = _markupHelperService.QueryPostMenuKeyboard(dbUser, post); - string postStatus = post.Status switch - { - PostStatus.ConfirmTimeout => "投递超时", - PostStatus.ReviewTimeout => "审核超时", - PostStatus.Rejected => "已拒绝", - PostStatus.Accepted => "已发布", + string postStatus = post.Status switch { + EPostStatus.ConfirmTimeout => "投递超时", + EPostStatus.ReviewTimeout => "审核超时", + EPostStatus.Rejected => "已拒绝", + EPostStatus.Accepted => "已发布", _ => "未知", }; string postMode = post.IsDirectPost ? "直接发布" : (post.Anonymous ? "匿名投稿" : "保留来源"); diff --git a/XinjingdailyBot.Service/Bot/Handler/GroupMessageHandler.cs b/XinjingdailyBot.Service/Bot/Handler/GroupMessageHandler.cs index 284d5b0e..51ecb8ea 100644 --- a/XinjingdailyBot.Service/Bot/Handler/GroupMessageHandler.cs +++ b/XinjingdailyBot.Service/Bot/Handler/GroupMessageHandler.cs @@ -37,7 +37,7 @@ public async Task OnGroupTextMessageReceived(Users dbUser, Message message) //制裁复读机 if (message.Text == replyMessage.Text) { - if (dbUser.Right.HasFlag(UserRights.AdminCmd) || dbUser.Right.HasFlag(UserRights.SuperCmd)) + if (dbUser.Right.HasFlag(EUserRights.AdminCmd) || dbUser.Right.HasFlag(EUserRights.SuperCmd)) { await _botClient.AutoReplyAsync("原来是狗管理, 惹不起惹不起...", message); } @@ -52,7 +52,7 @@ public async Task OnGroupTextMessageReceived(Users dbUser, Message message) try { ChatPermissions permission = new() { CanSendMessages = false, }; - await _botClient.RestrictChatMemberAsync(chatId, dbUser.UserID, permission, banTime); + await _botClient.RestrictChatMemberAsync(chatId, dbUser.UserID, permission, untilDate: banTime); } catch { @@ -65,7 +65,7 @@ public async Task OnGroupTextMessageReceived(Users dbUser, Message message) if (message.Text == "爬" || message.Text == "爪巴") { - if (dbUser.Right.HasFlag(UserRights.AdminCmd) || dbUser.Right.HasFlag(UserRights.SuperCmd)) + if (dbUser.Right.HasFlag(EUserRights.AdminCmd) || dbUser.Right.HasFlag(EUserRights.SuperCmd)) { await _botClient.AutoReplyAsync("嗻", message); } diff --git a/XinjingdailyBot.Service/Bot/Handler/InlineQueryHandler.cs b/XinjingdailyBot.Service/Bot/Handler/InlineQueryHandler.cs index d9d2a8b6..87bc169b 100644 --- a/XinjingdailyBot.Service/Bot/Handler/InlineQueryHandler.cs +++ b/XinjingdailyBot.Service/Bot/Handler/InlineQueryHandler.cs @@ -34,14 +34,14 @@ public InlineQueryHandler( public async Task OnInlineQueryReceived(Users dbUser, InlineQuery query) { - if (dbUser.Right.HasFlag(UserRights.AdminCmd)) + if (dbUser.Right.HasFlag(EUserRights.AdminCmd)) { List results = new(); for (int i = 0; i < 10; i++) { var randomPost = await _postService.Queryable() - .Where(x => x.Status == PostStatus.Accepted && x.PostType == MessageType.Photo) + .Where(x => x.Status == EPostStatus.Accepted && x.PostType == MessageType.Photo) .OrderBy(x => SqlFunc.GetRandom()).Take(1).FirstAsync(); if (randomPost == null) @@ -51,8 +51,7 @@ public async Task OnInlineQueryReceived(Users dbUser, InlineQuery query) var postAttachment = await _attachmentService.Queryable().Where(x => x.PostID == randomPost.Id).FirstAsync(); var keyboard = _markupHelperService.LinkToOriginPostKeyboard(randomPost); - results.Add(new InlineQueryResultCachedPhoto(i.ToString(), postAttachment.FileID) - { + results.Add(new InlineQueryResultCachedPhoto(i.ToString(), postAttachment.FileID) { Title = randomPost.Text, Description = randomPost.Text, Caption = randomPost.Text, diff --git a/XinjingdailyBot.Service/Data/AttachmentService.cs b/XinjingdailyBot.Service/Data/AttachmentService.cs index f2178ae1..d6cd4ef7 100644 --- a/XinjingdailyBot.Service/Data/AttachmentService.cs +++ b/XinjingdailyBot.Service/Data/AttachmentService.cs @@ -95,8 +95,7 @@ public sealed class AttachmentService : BaseService, IAttachmentSer return null; } - Attachments result = new() - { + Attachments result = new() { PostID = postID, FileID = fileID, FileName = fileName, diff --git a/XinjingdailyBot.Service/Data/ChannelOptionService.cs b/XinjingdailyBot.Service/Data/ChannelOptionService.cs index 78d2537e..9ee96b01 100644 --- a/XinjingdailyBot.Service/Data/ChannelOptionService.cs +++ b/XinjingdailyBot.Service/Data/ChannelOptionService.cs @@ -1,4 +1,5 @@ -using XinjingdailyBot.Infrastructure.Attribute; +using Telegram.Bot.Types; +using XinjingdailyBot.Infrastructure.Attribute; using XinjingdailyBot.Infrastructure.Enums; using XinjingdailyBot.Interface.Data; using XinjingdailyBot.Model.Models; @@ -9,17 +10,20 @@ namespace XinjingdailyBot.Service.Data [AppService(typeof(IChannelOptionService), LifeTime.Transient)] public sealed class ChannelOptionService : BaseService, IChannelOptionService { - public async Task FetchChannelOption(long channelId, string? channelName, string? channelTitle) + public async Task FetchChannelOption(Chat channelChat) { - var channel = await Queryable().Where(x => x.ChannelID == channelId).FirstAsync(); + var chatId = channelChat.Id; + var chatTitle = channelChat.Title; + var chatUserName = channelChat.Username; + + var channel = await Queryable().Where(x => x.ChannelID == chatId).FirstAsync(); if (channel == null) { - channel = new() - { - ChannelID = channelId, - ChannelName = channelName ?? "", - ChannelTitle = channelTitle ?? "", - Option = ChannelOption.Normal, + channel = new ChannelOptions { + ChannelID = chatId, + ChannelName = chatUserName ?? "", + ChannelTitle = chatTitle ?? "", + Option = EChannelOption.Normal, Count = 1, CreateAt = DateTime.Now, ModifyAt = DateTime.Now, @@ -28,10 +32,10 @@ public async Task FetchChannelOption(long channelId, string? chan } else { - if (channel.ChannelName != channelName || channel.ChannelTitle != channelTitle) + if (channel.ChannelName != chatUserName || channel.ChannelTitle != chatTitle) { - channel.ChannelTitle = channelTitle ?? ""; - channel.ChannelName = channelName ?? ""; + channel.ChannelTitle = chatTitle ?? ""; + channel.ChannelName = chatUserName ?? ""; channel.ModifyAt = DateTime.Now; } channel.Count++; @@ -47,7 +51,23 @@ public async Task FetchChannelOption(long channelId, string? chan return channel; } - public async Task UpdateChannelOptionById(long channelId, ChannelOption channelOption) + public async Task FetchChannelByNameOrTitle(string channelName, string channelTitle) + { + var channel = await Queryable().Where(x => x.ChannelName == channelName || x.ChannelTitle == channelTitle).FirstAsync(); + return channel; + } + + public async Task FetchChannelByChannelId(long channelId) + { + if (channelId <= 0) + { + return null; + } + var channel = await Queryable().Where(x => x.ChannelID == channelId).FirstAsync(); + return channel; + } + + public async Task UpdateChannelOptionById(long channelId, EChannelOption channelOption) { var channel = await Queryable().Where(x => x.ChannelID == channelId).FirstAsync(); if (channel != null) diff --git a/XinjingdailyBot.Service/Data/ChatStateService.cs b/XinjingdailyBot.Service/Data/ChatStateService.cs deleted file mode 100644 index e29a28bf..00000000 --- a/XinjingdailyBot.Service/Data/ChatStateService.cs +++ /dev/null @@ -1,16 +0,0 @@ -using XinjingdailyBot.Infrastructure.Attribute; -using XinjingdailyBot.Interface.Data; -using XinjingdailyBot.Model.Models; -using XinjingdailyBot.Service.Data.Base; - -namespace XinjingdailyBot.Service.Data -{ - [AppService(typeof(IChatStateService), LifeTime.Transient)] - public sealed class ChatStateService : BaseService, IChatStateService - { - public bool If() - { - return true; - } - } -} diff --git a/XinjingdailyBot.Service/Data/CmdRecordService.cs b/XinjingdailyBot.Service/Data/CmdRecordService.cs index 31cdf1bd..7eb6751a 100644 --- a/XinjingdailyBot.Service/Data/CmdRecordService.cs +++ b/XinjingdailyBot.Service/Data/CmdRecordService.cs @@ -19,8 +19,7 @@ public async Task AddCmdRecord(Message message, Users dbUser, bool handled, bool text = text[..1000]; } - CmdRecords record = new() - { + CmdRecords record = new() { ChatID = message.Chat.Id, MessageID = message.MessageId, UserID = dbUser.UserID, @@ -46,8 +45,7 @@ public async Task AddCmdRecord(CallbackQuery query, Users dbUser, bool handled, } var message = query.Message!; - CmdRecords record = new() - { + CmdRecords record = new() { ChatID = message.Chat.Id, MessageID = message.MessageId, UserID = dbUser.UserID, diff --git a/XinjingdailyBot.Service/Data/DialogueService.cs b/XinjingdailyBot.Service/Data/DialogueService.cs index 40b42343..c3fbe76e 100644 --- a/XinjingdailyBot.Service/Data/DialogueService.cs +++ b/XinjingdailyBot.Service/Data/DialogueService.cs @@ -12,8 +12,7 @@ public sealed class DialogueService : BaseService, IDialogueService { public async Task RecordMessage(Message message) { - string? content = message.Type switch - { + string? content = message.Type switch { MessageType.Text => message.Text, MessageType.Photo => message.Caption, MessageType.Audio => message.Caption, @@ -29,15 +28,14 @@ public async Task RecordMessage(Message message) content = content[..2000]; } - var dialogue = new Dialogue - { + var dialogue = new Dialogue { ChatID = message.Chat.Id, MessageID = message.MessageId, UserID = message.From?.Id ?? -1, ReplyMessageID = message.ReplyToMessage?.MessageId ?? -1, Type = message.Type.ToString(), Content = content ?? "", - Date = message.Date, + CreateAt = message.Date, }; await InsertAsync(dialogue); diff --git a/XinjingdailyBot.Service/Data/MediaGroupService.cs b/XinjingdailyBot.Service/Data/MediaGroupService.cs index 2c87015f..28eb1ffc 100644 --- a/XinjingdailyBot.Service/Data/MediaGroupService.cs +++ b/XinjingdailyBot.Service/Data/MediaGroupService.cs @@ -12,8 +12,7 @@ public sealed class MediaGroupService : BaseService, IMediaGroupSer { public async Task AddPostMediaGroup(Message message) { - var postGeoup = new MediaGroups - { + var postGeoup = new MediaGroups { ChatID = message.Chat.Id, MessageID = message.MessageId, MediaGroupID = message.MediaGroupId!, @@ -26,8 +25,7 @@ public async Task AddPostMediaGroup(Message message) public async Task AddPostMediaGroup(IEnumerable messages) { var now = DateTime.Now; - var postGeoups = messages.Select(x => new MediaGroups - { + var postGeoups = messages.Select(x => new MediaGroups { ChatID = x.Chat.Id, MessageID = x.MessageId, MediaGroupID = x.MediaGroupId!, @@ -49,10 +47,16 @@ public async Task> QueryMediaGroup(string? mediaGroupId) return mediaGroups; } - public async Task QueryMediaGroup(Chat chat,long msgId) + public async Task QueryMediaGroup(Chat chat, long msgId) { var mediaGroup = await Queryable().FirstAsync(x => x.ChatID == chat.Id && x.MessageID == msgId); return mediaGroup; } + + public async Task QueryMediaGroup(long chatId, int msgId) + { + var mediaGroup = await Queryable().FirstAsync(x => x.ChatID == chatId && x.MessageID == msgId); + return mediaGroup; + } } } diff --git a/XinjingdailyBot.Service/Data/NameHistoryService.cs b/XinjingdailyBot.Service/Data/NameHistoryService.cs index d853371e..bdbce6d1 100644 --- a/XinjingdailyBot.Service/Data/NameHistoryService.cs +++ b/XinjingdailyBot.Service/Data/NameHistoryService.cs @@ -1,19 +1,6 @@ -using System.Text; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; -using SqlSugar; -using Telegram.Bot; -using Telegram.Bot.Types; -using Telegram.Bot.Types.Enums; -using Telegram.Bot.Types.ReplyMarkups; -using XinjingdailyBot.Infrastructure; -using XinjingdailyBot.Infrastructure.Attribute; -using XinjingdailyBot.Infrastructure.Extensions; -using XinjingdailyBot.Interface.Bot.Common; +using XinjingdailyBot.Infrastructure.Attribute; using XinjingdailyBot.Interface.Data; -using XinjingdailyBot.Interface.Helper; using XinjingdailyBot.Model.Models; -using XinjingdailyBot.Repository; using XinjingdailyBot.Service.Data.Base; namespace XinjingdailyBot.Service.Data @@ -23,8 +10,7 @@ public sealed class NameHistoryService : BaseService, INameHistoryS { public async Task CreateNameHistory(Users dbUser) { - var history = new NameHistory - { + var history = new NameHistory { UId = dbUser.Id, FirstName = dbUser.FirstName, LastName = dbUser.LastName, diff --git a/XinjingdailyBot.Service/Data/PostService.cs b/XinjingdailyBot.Service/Data/PostService.cs index e41c16c7..f11f7bed 100644 --- a/XinjingdailyBot.Service/Data/PostService.cs +++ b/XinjingdailyBot.Service/Data/PostService.cs @@ -1,6 +1,6 @@ -using System.Collections.Concurrent; -using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; +using System.Collections.Concurrent; using Telegram.Bot; using Telegram.Bot.Types; using Telegram.Bot.Types.Enums; @@ -19,7 +19,7 @@ namespace XinjingdailyBot.Service.Data { [AppService(typeof(IPostService), LifeTime.Singleton)] - public sealed class PostService : BaseService, IPostService + public sealed class PostService : BaseService, IPostService { private readonly ILogger _logger; private readonly IAttachmentService _attachmentService; @@ -62,7 +62,7 @@ public PostService( public async Task CheckPostLimit(Users dbUser, Message? message = null, CallbackQuery? query = null) { //未开启限制或者用户为管理员时不受限制 - if ((dbUser.AcceptCount > 0 && !_postOption.EnablePostLimit) || dbUser.Right.HasFlag(UserRights.Admin)) + if ((dbUser.AcceptCount > 0 && !_postOption.EnablePostLimit) || dbUser.Right.HasFlag(EUserRights.Admin)) { return true; } @@ -87,59 +87,41 @@ public async Task CheckPostLimit(Users dbUser, Message? message = null, Ca DateTime now = DateTime.Now; DateTime today = now.AddHours(-now.Hour).AddMinutes(-now.Minute).AddSeconds(-now.Second); - //待确认 - var paddingCount = await Queryable() - .Where(x => x.PosterUID == dbUser.UserID && x.CreateAt >= today && x.Status == PostStatus.Padding) - .CountAsync(); - - if (paddingCount >= paddingLimit) + if (message != null) { - if (message != null) + //待确认 + var paddingCount = await Queryable() + .Where(x => x.PosterUID == dbUser.UserID && x.CreateAt >= today && x.Status == EPostStatus.Padding) + .CountAsync(); + + if (paddingCount >= paddingLimit) { await _botClient.AutoReplyAsync($"您的投稿队列已满 {paddingCount} / {paddingLimit}, 请先处理尚未确认的稿件", message); + return false; } - if (query != null) - { - await _botClient.AutoReplyAsync($"您的投稿队列已满 {paddingCount} / {paddingLimit}, 请先处理尚未确认的稿件", query, true); - } - return false; - } - //审核中 - var reviewCount = await Queryable() - .Where(x => x.PosterUID == dbUser.UserID && x.CreateAt >= today && x.Status == PostStatus.Reviewing) - .CountAsync(); + //已通过 + 已拒绝(非重复 / 模糊原因) + var postCount = await Queryable() + .Where(x => x.PosterUID == dbUser.UserID && x.CreateAt >= today && (x.Status == EPostStatus.Accepted || (x.Status == EPostStatus.Rejected && x.CountReject))) + .CountAsync(); - if (reviewCount >= reviewLimit) - { - if (message != null) + if (postCount >= dailyLimit) { - await _botClient.AutoReplyAsync($"您的审核队列已满 {reviewCount} / {reviewLimit}, 请耐心等待队列中的稿件审核完毕", message); + await _botClient.AutoReplyAsync($"您已达到每日投稿上限 {postCount} / {dailyLimit}, 暂时无法继续投稿, 请明日再来", message); return true; } - if (query != null) - { - await _botClient.AutoReplyAsync($"您的审核队列已满 {reviewCount} / {reviewLimit}, 请耐心等待队列中的稿件审核完毕", query, true); - return false; - } } - //已通过 + 已拒绝(非重复/模糊原因) - var postCount = await Queryable() - .Where(x => x.PosterUID == dbUser.UserID && x.CreateAt >= today && - (x.Status == PostStatus.Accepted || (x.Status == PostStatus.Rejected && x.Reason != RejectReason.Duplicate && x.Reason != RejectReason.Fuzzy))) - .CountAsync(); - - if (postCount >= dailyLimit) + if (query != null) { - if (message != null) - { - await _botClient.AutoReplyAsync($"您已达到每日投稿上限 {postCount} / {dailyLimit}, 暂时无法继续投稿, 请明日再来", message); - return true; - } - if (query != null) + //审核中 + var reviewCount = await Queryable() + .Where(x => x.PosterUID == dbUser.UserID && x.CreateAt >= today && x.Status == EPostStatus.Reviewing) + .CountAsync(); + + if (reviewCount >= reviewLimit) { - await _botClient.AutoReplyAsync($"您已达到每日投稿上限 {postCount} / {dailyLimit}, 暂时无法继续投稿, 请明日再来", query, true); + await _botClient.AutoReplyAsync($"您的审核队列已满 {reviewCount} / {reviewLimit}, 请耐心等待队列中的稿件审核完毕", query, true); return false; } } @@ -150,7 +132,7 @@ public async Task CheckPostLimit(Users dbUser, Message? message = null, Ca public async Task HandleTextPosts(Users dbUser, Message message) { - if (!dbUser.Right.HasFlag(UserRights.SendPost)) + if (!dbUser.Right.HasFlag(EUserRights.SendPost)) { await _botClient.AutoReplyAsync(Langs.NoPostRight, message); return; @@ -173,13 +155,14 @@ public async Task HandleTextPosts(Users dbUser, Message message) return; } - ChannelOption channelOption = ChannelOption.Normal; - string? channelName = null, channelTitle = null; + var channelOption = EChannelOption.Normal; + + long channelId = -1, channelMsgId = -1; if (message.ForwardFromChat?.Type == ChatType.Channel) { - long channelId = message.ForwardFromChat.Id; + channelId = message.ForwardFromChat.Id; //非管理员禁止从自己的频道转发 - if (!dbUser.Right.HasFlag(UserRights.ReviewPost)) + if (!dbUser.Right.HasFlag(EUserRights.ReviewPost)) { if (channelId == _channelService.AcceptChannel.Id || channelId == _channelService.RejectChannel.Id) { @@ -188,9 +171,8 @@ public async Task HandleTextPosts(Users dbUser, Message message) } } - channelTitle = message.ForwardFromChat.Title; - channelOption = await _channelOptionService.FetchChannelOption(channelId, message.ForwardFromChat.Username, channelTitle); - channelName = $"{message.ForwardFromChat.Username}/{message.ForwardFromMessageId}"; + channelMsgId = message.ForwardFromMessageId ?? -1; + channelOption = await _channelOptionService.FetchChannelOption(message.ForwardFromChat); } int newTags = _tagRepository.FetchTags(message.Text); @@ -199,23 +181,22 @@ public async Task HandleTextPosts(Users dbUser, Message message) bool anonymous = dbUser.PreferAnonymous; //直接发布模式 - bool directPost = dbUser.Right.HasFlag(UserRights.DirectPost); + bool directPost = dbUser.Right.HasFlag(EUserRights.DirectPost); //发送确认消息 var keyboard = directPost ? _markupHelperService.DirectPostKeyboard(anonymous, newTags, null) : _markupHelperService.PostKeyboard(anonymous); string postText = directPost ? "您具有直接投稿权限, 您的稿件将会直接发布" : "真的要投稿吗"; //生成数据库实体 - Posts newPost = new() - { + var newPost = new NewPosts { Anonymous = anonymous, Text = text, RawText = message.Text ?? "", - ChannelName = channelName ?? "", - ChannelTitle = channelTitle ?? "", - Status = directPost ? PostStatus.Reviewing : PostStatus.Padding, + ChannelID = channelId, + ChannelMsgId = channelMsgId, + Status = directPost ? EPostStatus.Reviewing : EPostStatus.Padding, PostType = message.Type, - NewTags = newTags, + Tags = newTags, HasSpoiler = message.HasMediaSpoiler ?? false, PosterUID = dbUser.UserID }; @@ -223,33 +204,35 @@ public async Task HandleTextPosts(Users dbUser, Message message) //套用频道设定 switch (channelOption) { - case ChannelOption.Normal: + case EChannelOption.Normal: break; - case ChannelOption.PurgeOrigin: + case EChannelOption.PurgeOrigin: postText += "\n由于系统设定, 来自该频道的投稿将不会显示来源"; - newPost.ChannelName += '~'; break; - case ChannelOption.AutoReject: + case EChannelOption.AutoReject: postText = "由于系统设定, 暂不接受来自此频道的投稿"; keyboard = null; - newPost.Status = PostStatus.Rejected; + newPost.Status = EPostStatus.Rejected; break; default: _logger.LogError("未知的频道选项 {channelOption}", channelOption); return; } - Message msg = await _botClient.SendTextMessageAsync(message.Chat.Id, postText, replyToMessageId: message.MessageId, replyMarkup: keyboard, allowSendingWithoutReply: true); + var actionMsg = await _botClient.SendTextMessageAsync(message.Chat.Id, postText, replyToMessageId: message.MessageId, replyMarkup: keyboard, allowSendingWithoutReply: true); //修改数据库实体 newPost.OriginChatID = message.Chat.Id; newPost.OriginMsgID = message.MessageId; - newPost.ActionMsgID = msg.MessageId; + newPost.OriginActionChatID = actionMsg.Chat.Id; + newPost.OriginActionMsgID = actionMsg.MessageId; if (directPost) { - newPost.ReviewMsgID = msg.MessageId; - newPost.ManageMsgID = msg.MessageId; + newPost.ReviewChatID = newPost.OriginChatID; + newPost.ReviewMsgID = newPost.OriginMsgID; + newPost.ReviewActionChatID = newPost.OriginActionChatID; + newPost.ReviewActionMsgID = newPost.OriginActionMsgID; } await Insertable(newPost).ExecuteCommandAsync(); @@ -257,7 +240,7 @@ public async Task HandleTextPosts(Users dbUser, Message message) public async Task HandleMediaPosts(Users dbUser, Message message) { - if (!dbUser.Right.HasFlag(UserRights.SendPost)) + if (!dbUser.Right.HasFlag(EUserRights.SendPost)) { await _botClient.AutoReplyAsync("没有权限", message); return; @@ -268,13 +251,14 @@ public async Task HandleMediaPosts(Users dbUser, Message message) return; } - ChannelOption channelOption = ChannelOption.Normal; - string? channelName = null, channelTitle = null; + var channelOption = EChannelOption.Normal; + + long channelId = -1, channelMsgId = -1; if (message.ForwardFromChat?.Type == ChatType.Channel) { - long channelId = message.ForwardFromChat.Id; + channelId = message.ForwardFromChat.Id; //非管理员禁止从自己的频道转发 - if (!dbUser.Right.HasFlag(UserRights.ReviewPost)) + if (!dbUser.Right.HasFlag(EUserRights.ReviewPost)) { if (channelId == _channelService.AcceptChannel.Id || channelId == _channelService.RejectChannel.Id) { @@ -282,20 +266,17 @@ public async Task HandleMediaPosts(Users dbUser, Message message) return; } } - - channelTitle = message.ForwardFromChat.Title; - channelOption = await _channelOptionService.FetchChannelOption(channelId, message.ForwardFromChat.Username, channelTitle); - channelName = $"{message.ForwardFromChat.Username}/{message.ForwardFromMessageId}"; + channelMsgId = message.ForwardFromMessageId ?? -1; + channelOption = await _channelOptionService.FetchChannelOption(message.ForwardFromChat); } - //BuildInTags tags = _textHelperService.FetchTags(message.Caption); int newTags = _tagRepository.FetchTags(message.Caption); string text = _textHelperService.ParseMessage(message); bool anonymous = dbUser.PreferAnonymous; //直接发布模式 - bool directPost = dbUser.Right.HasFlag(UserRights.DirectPost); + bool directPost = dbUser.Right.HasFlag(EUserRights.DirectPost); bool? hasSpoiler = message.CanSpoiler() ? message.HasMediaSpoiler ?? false : null; @@ -306,16 +287,15 @@ public async Task HandleMediaPosts(Users dbUser, Message message) string postText = directPost ? "您具有直接投稿权限, 您的稿件将会直接发布" : "真的要投稿吗"; //生成数据库实体 - Posts newPost = new() - { + var newPost = new NewPosts { Anonymous = anonymous, Text = text, RawText = message.Text ?? "", - ChannelName = channelName ?? "", - ChannelTitle = channelTitle ?? "", - Status = directPost ? PostStatus.Reviewing : PostStatus.Padding, + ChannelID = channelId, + ChannelMsgId = channelMsgId, + Status = directPost ? EPostStatus.Reviewing : EPostStatus.Padding, PostType = message.Type, - NewTags = newTags, + Tags = newTags, HasSpoiler = message.HasMediaSpoiler ?? false, PosterUID = dbUser.UserID }; @@ -323,33 +303,35 @@ public async Task HandleMediaPosts(Users dbUser, Message message) //套用频道设定 switch (channelOption) { - case ChannelOption.Normal: + case EChannelOption.Normal: break; - case ChannelOption.PurgeOrigin: + case EChannelOption.PurgeOrigin: postText += "\n由于系统设定, 来自该频道的投稿将不会显示来源"; - newPost.ChannelName += '~'; break; - case ChannelOption.AutoReject: + case EChannelOption.AutoReject: postText = "由于系统设定, 暂不接受来自此频道的投稿"; keyboard = null; - newPost.Status = PostStatus.Rejected; + newPost.Status = EPostStatus.Rejected; break; default: _logger.LogError("未知的频道选项 {channelOption}", channelOption); return; } - Message msg = await _botClient.SendTextMessageAsync(message.Chat.Id, postText, replyToMessageId: message.MessageId, replyMarkup: keyboard, allowSendingWithoutReply: true); + var actionMsg = await _botClient.SendTextMessageAsync(message.Chat.Id, postText, replyToMessageId: message.MessageId, replyMarkup: keyboard, allowSendingWithoutReply: true); //修改数据库实体 newPost.OriginChatID = message.Chat.Id; newPost.OriginMsgID = message.MessageId; - newPost.ActionMsgID = msg.MessageId; + newPost.OriginActionChatID = actionMsg.Chat.Id; + newPost.OriginActionMsgID = actionMsg.MessageId; if (directPost) { - newPost.ReviewMsgID = msg.MessageId; - newPost.ManageMsgID = msg.MessageId; + newPost.ReviewChatID = newPost.OriginChatID; + newPost.ReviewMsgID = newPost.OriginMsgID; + newPost.ReviewActionChatID = newPost.OriginActionChatID; + newPost.ReviewActionMsgID = newPost.OriginActionMsgID; } long postID = await Insertable(newPost).ExecuteReturnBigIdentityAsync(); @@ -369,7 +351,7 @@ public async Task HandleMediaPosts(Users dbUser, Message message) public async Task HandleMediaGroupPosts(Users dbUser, Message message) { - if (!dbUser.Right.HasFlag(UserRights.SendPost)) + if (!dbUser.Right.HasFlag(EUserRights.SendPost)) { await _botClient.AutoReplyAsync("没有权限", message); return; @@ -385,16 +367,17 @@ public async Task HandleMediaGroupPosts(Users dbUser, Message message) { MediaGroupIDs.TryAdd(mediaGroupId, -1); - bool exists = await Queryable().AnyAsync(x => x.MediaGroupID == mediaGroupId); + bool exists = await Queryable().AnyAsync(x => x.OriginMediaGroupID == mediaGroupId); if (!exists) { - ChannelOption channelOption = ChannelOption.Normal; - string? channelName = null, channelTitle = null; + var channelOption = EChannelOption.Normal; + + long channelId = -1, channelMsgId = -1; if (message.ForwardFromChat?.Type == ChatType.Channel) { - long channelId = message.ForwardFromChat.Id; + channelId = message.ForwardFromChat.Id; //非管理员禁止从自己的频道转发 - if (!dbUser.Right.HasFlag(UserRights.ReviewPost)) + if (!dbUser.Right.HasFlag(EUserRights.ReviewPost)) { if (channelId == _channelService.AcceptChannel.Id || channelId == _channelService.RejectChannel.Id) { @@ -403,9 +386,8 @@ public async Task HandleMediaGroupPosts(Users dbUser, Message message) } } - channelTitle = message.ForwardFromChat.Title; - channelOption = await _channelOptionService.FetchChannelOption(channelId, message.ForwardFromChat.Username, channelTitle); - channelName = $"{message.ForwardFromChat.Username}/{message.ForwardFromMessageId}"; + channelMsgId = message.ForwardFromMessageId ?? -1; + channelOption = await _channelOptionService.FetchChannelOption(message.ForwardFromChat); } int newTags = _tagRepository.FetchTags(message.Caption); @@ -414,7 +396,7 @@ public async Task HandleMediaGroupPosts(Users dbUser, Message message) bool anonymous = dbUser.PreferAnonymous; //直接发布模式 - bool directPost = dbUser.Right.HasFlag(UserRights.DirectPost); + bool directPost = dbUser.Right.HasFlag(EUserRights.DirectPost); bool? hasSpoiler = message.CanSpoiler() ? message.HasMediaSpoiler ?? false : null; //发送确认消息 @@ -423,23 +405,23 @@ public async Task HandleMediaGroupPosts(Users dbUser, Message message) _markupHelperService.PostKeyboard(anonymous); string postText = directPost ? "您具有直接投稿权限, 您的稿件将会直接发布" : "真的要投稿吗"; - Message msg = await _botClient.SendTextMessageAsync(message.Chat.Id, "处理中, 请稍后", replyToMessageId: message.MessageId, allowSendingWithoutReply: true); + var actionMsg = await _botClient.SendTextMessageAsync(message.Chat.Id, "处理中, 请稍后", replyToMessageId: message.MessageId, allowSendingWithoutReply: true); //生成数据库实体 - Posts newPost = new() - { + var newPost = new NewPosts { OriginChatID = message.Chat.Id, OriginMsgID = message.MessageId, - ActionMsgID = msg.MessageId, + OriginActionChatID = actionMsg.Chat.Id, + OriginActionMsgID = actionMsg.MessageId, Anonymous = anonymous, Text = text, RawText = message.Text ?? "", - ChannelName = channelName ?? "", - ChannelTitle = channelTitle ?? "", - Status = directPost ? PostStatus.Reviewing : PostStatus.Padding, + ChannelID = channelId, + ChannelMsgId = channelMsgId, + Status = directPost ? EPostStatus.Reviewing : EPostStatus.Padding, PostType = message.Type, - MediaGroupID = mediaGroupId, - NewTags = newTags, + OriginMediaGroupID = mediaGroupId, + Tags = newTags, HasSpoiler = hasSpoiler ?? false, PosterUID = dbUser.UserID, }; @@ -447,16 +429,15 @@ public async Task HandleMediaGroupPosts(Users dbUser, Message message) //套用频道设定 switch (channelOption) { - case ChannelOption.Normal: + case EChannelOption.Normal: break; - case ChannelOption.PurgeOrigin: + case EChannelOption.PurgeOrigin: postText += "\n由于系统设定, 来自该频道的投稿将不会显示来源"; - newPost.ChannelName += '~'; break; - case ChannelOption.AutoReject: + case EChannelOption.AutoReject: postText = "由于系统设定, 暂不接受来自此频道的投稿"; keyboard = null; - newPost.Status = PostStatus.Rejected; + newPost.Status = EPostStatus.Rejected; break; default: _logger.LogError("未知的频道选项 {channelOption}", channelOption); @@ -465,8 +446,10 @@ public async Task HandleMediaGroupPosts(Users dbUser, Message message) if (directPost) { - newPost.ReviewMsgID = msg.MessageId; - newPost.ManageMsgID = msg.MessageId; + newPost.ReviewChatID = newPost.OriginChatID; + newPost.ReviewMsgID = newPost.OriginMsgID; + newPost.ReviewActionChatID = newPost.OriginActionChatID; + newPost.ReviewActionMsgID = newPost.OriginActionMsgID; } postID = await Insertable(newPost).ExecuteReturnIdentityAsync(); @@ -474,12 +457,11 @@ public async Task HandleMediaGroupPosts(Users dbUser, Message message) MediaGroupIDs[mediaGroupId] = postID; //两秒后停止接收媒体组消息 - _ = Task.Run(async () => - { + _ = Task.Run(async () => { await Task.Delay(1500); MediaGroupIDs.Remove(mediaGroupId, out _); - await _botClient.EditMessageTextAsync(msg, postText, replyMarkup: keyboard); + await _botClient.EditMessageTextAsync(actionMsg, postText, replyMarkup: keyboard); }); } } @@ -496,7 +478,7 @@ public async Task HandleMediaGroupPosts(Users dbUser, Message message) } } - public async Task SetPostTag(Posts post, int tagId, CallbackQuery callbackQuery) + public async Task SetPostTag(NewPosts post, int tagId, CallbackQuery callbackQuery) { var tag = _tagRepository.GetTagById(tagId); if (tag == null) @@ -504,31 +486,31 @@ public async Task SetPostTag(Posts post, int tagId, CallbackQuery callbackQuery) return; } - if ((post.NewTags & tag.Seg) > 0) + if ((post.Tags & tag.Seg) > 0) { - post.NewTags &= ~tag.Seg; + post.Tags &= ~tag.Seg; } else { - post.NewTags |= tag.Seg; + post.Tags |= tag.Seg; } - string tagName = _tagRepository.GetActiviedTagsName(post.NewTags); + string tagName = _tagRepository.GetActiviedTagsName(post.Tags); post.ModifyAt = DateTime.Now; - await Updateable(post).UpdateColumns(x => new { x.NewTags, x.ModifyAt }).ExecuteCommandAsync(); + await Updateable(post).UpdateColumns(x => new { x.Tags, x.ModifyAt }).ExecuteCommandAsync(); await _botClient.AutoReplyAsync($"当前标签: {tagName}", callbackQuery); bool? hasSpoiler = post.CanSpoiler ? post.HasSpoiler : null; var keyboard = post.IsDirectPost ? - _markupHelperService.DirectPostKeyboard(post.Anonymous, post.NewTags, hasSpoiler) : - _markupHelperService.ReviewKeyboardA(post.NewTags, hasSpoiler); + _markupHelperService.DirectPostKeyboard(post.Anonymous, post.Tags, hasSpoiler) : + _markupHelperService.ReviewKeyboardA(post.Tags, hasSpoiler); await _botClient.EditMessageReplyMarkupAsync(callbackQuery.Message!, keyboard); } - public async Task SetPostTag(Posts post, string payload, CallbackQuery callbackQuery) + public async Task SetPostTag(NewPosts post, string payload, CallbackQuery callbackQuery) { payload = payload.ToLowerInvariant(); var tag = _tagRepository.GetTagByPayload(payload); @@ -538,18 +520,26 @@ public async Task SetPostTag(Posts post, string payload, CallbackQuery callbackQ } } - public async Task RejetPost(Posts post, Users dbUser, string rejectReason) + public async Task RejetPost(NewPosts post, Users dbUser, RejectReasons rejectReason) { + post.RejectReason = rejectReason.Name; + post.CountReject = rejectReason.IsCount; post.ReviewerUID = dbUser.UserID; - post.Status = PostStatus.Rejected; + post.Status = EPostStatus.Rejected; post.ModifyAt = DateTime.Now; - await Updateable(post).UpdateColumns(x => new { x.Reason, x.ReviewerUID, x.Status, x.ModifyAt }).ExecuteCommandAsync(); + await Updateable(post).UpdateColumns(x => new { + x.RejectReason, + x.CountReject, + x.ReviewerUID, + x.Status, + x.ModifyAt + }).ExecuteCommandAsync(); - Users poster = await _userService.Queryable().FirstAsync(x => x.UserID == post.PosterUID); + var poster = await _userService.Queryable().FirstAsync(x => x.UserID == post.PosterUID); //修改审核群消息 - string reviewMsg = _textHelperService.MakeReviewMessage(poster, dbUser, post.Anonymous, rejectReason); - await _botClient.EditMessageTextAsync(_channelService.ReviewGroup.Id, (int)post.ManageMsgID, reviewMsg, parseMode: ParseMode.Html, disableWebPagePreview: true); + string reviewMsg = _textHelperService.MakeReviewMessage(poster, dbUser, post.Anonymous, rejectReason.FullText); + await _botClient.EditMessageTextAsync(post.ReviewActionChatID, (int)post.ReviewActionMsgID, reviewMsg, parseMode: ParseMode.Html, disableWebPagePreview: true); //拒稿频道发布消息 if (!post.IsMediaGroup) @@ -558,8 +548,7 @@ public async Task RejetPost(Posts post, Users dbUser, string rejectReason) { var attachment = await _attachmentService.Queryable().Where(x => x.PostID == post.Id).FirstAsync(); - var handler = post.PostType switch - { + var handler = post.PostType switch { MessageType.Photo => _botClient.SendPhotoAsync(_channelService.RejectChannel.Id, new InputFileId(attachment.FileID)), MessageType.Audio => _botClient.SendAudioAsync(_channelService.RejectChannel.Id, new InputFileId(attachment.FileID)), MessageType.Video => _botClient.SendVideoAsync(_channelService.RejectChannel.Id, new InputFileId(attachment.FileID)), @@ -581,37 +570,49 @@ public async Task RejetPost(Posts post, Users dbUser, string rejectReason) var group = new IAlbumInputMedia[attachments.Count]; for (int i = 0; i < attachments.Count; i++) { - MessageType attachmentType = attachments[i].Type; + var attachmentType = attachments[i].Type; if (attachmentType == MessageType.Unknown) { attachmentType = post.PostType; } - group[i] = attachmentType switch - { + group[i] = attachmentType switch { MessageType.Photo => new InputMediaPhoto(new InputFileId(attachments[i].FileID)), MessageType.Audio => new InputMediaAudio(new InputFileId(attachments[i].FileID)), MessageType.Video => new InputMediaVideo(new InputFileId(attachments[i].FileID)), MessageType.Voice => new InputMediaAudio(new InputFileId(attachments[i].FileID)), MessageType.Document => new InputMediaDocument(new InputFileId(attachments[i].FileID)), - //MessageType.Animation 不支持媒体组 _ => throw new Exception("未知的稿件类型"), }; } - var messages = await _botClient.SendMediaGroupAsync(_channelService.RejectChannel.Id, group); + var postMessages = await _botClient.SendMediaGroupAsync(_channelService.RejectChannel.Id, group); + + var postMessage = postMessages.FirstOrDefault(); + if (postMessage != null) + { + post.PublicMsgID = postMessage.MessageId; + post.PublishMediaGroupID = postMessage.MediaGroupId ?? ""; + post.ModifyAt = DateTime.Now; + + await Updateable(post).UpdateColumns(x => new { + x.PublicMsgID, + x.PublishMediaGroupID, + x.ModifyAt + }).ExecuteCommandAsync(); + } //处理媒体组消息 - await _mediaGroupService.AddPostMediaGroup(messages); + await _mediaGroupService.AddPostMediaGroup(postMessages); } //通知投稿人 - string posterMsg = _textHelperService.MakeNotification(rejectReason); + string posterMsg = _textHelperService.MakeNotification(rejectReason.FullText); if (poster.Notification) { await _botClient.SendTextMessageAsync(post.OriginChatID, posterMsg, replyToMessageId: (int)post.OriginMsgID, allowSendingWithoutReply: true); } else { - await _botClient.EditMessageTextAsync(post.OriginChatID, (int)post.ActionMsgID, posterMsg); + await _botClient.EditMessageTextAsync(post.OriginActionChatID, (int)post.OriginActionMsgID, posterMsg); } poster.RejectCount++; @@ -626,39 +627,39 @@ public async Task RejetPost(Posts post, Users dbUser, string rejectReason) } } - public async Task AcceptPost(Posts post, Users dbUser, CallbackQuery callbackQuery) + public async Task AcceptPost(NewPosts post, Users dbUser, CallbackQuery callbackQuery) { - Users poster = await _userService.Queryable().FirstAsync(x => x.UserID == post.PosterUID); + var poster = await _userService.Queryable().FirstAsync(x => x.UserID == post.PosterUID); if (post.IsDirectPost) { poster.PostCount++; } - string postText = _textHelperService.MakePostText(post, poster); + var channel = await _channelOptionService.FetchChannelByChannelId(post.ChannelID); + string postText = _textHelperService.MakePostText(post, poster, channel); bool hasSpoiler = post.HasSpoiler; //发布频道发布消息 if (!post.IsMediaGroup) { - string? warnText = _tagRepository.GetActivedTagWarnings(post.NewTags); + string? warnText = _tagRepository.GetActivedTagWarnings(post.Tags); if (!string.IsNullOrEmpty(warnText)) { await _botClient.SendTextMessageAsync(_channelService.AcceptChannel.Id, warnText, allowSendingWithoutReply: true); } - Message? msg = null; + Message? postMessage = null; if (post.PostType == MessageType.Text) { - msg = await _botClient.SendTextMessageAsync(_channelService.AcceptChannel.Id, postText, parseMode: ParseMode.Html, disableWebPagePreview: true); + postMessage = await _botClient.SendTextMessageAsync(_channelService.AcceptChannel.Id, postText, parseMode: ParseMode.Html, disableWebPagePreview: true); } else { - Attachments attachment = await _attachmentService.Queryable().FirstAsync(x => x.PostID == post.Id); + var attachment = await _attachmentService.Queryable().FirstAsync(x => x.PostID == post.Id); - var handler = post.PostType switch - { + var handler = post.PostType switch { MessageType.Photo => _botClient.SendPhotoAsync(_channelService.AcceptChannel.Id, new InputFileId(attachment.FileID), caption: postText, parseMode: ParseMode.Html, hasSpoiler: hasSpoiler), MessageType.Audio => _botClient.SendAudioAsync(_channelService.AcceptChannel.Id, new InputFileId(attachment.FileID), caption: postText, parseMode: ParseMode.Html, title: attachment.FileName), MessageType.Video => _botClient.SendVideoAsync(_channelService.AcceptChannel.Id, new InputFileId(attachment.FileID), caption: postText, parseMode: ParseMode.Html, hasSpoiler: hasSpoiler), @@ -674,9 +675,9 @@ public async Task AcceptPost(Posts post, Users dbUser, CallbackQuery callbackQue return; } - msg = await handler; + postMessage = await handler; } - post.PublicMsgID = msg?.MessageId ?? -1; + post.PublicMsgID = postMessage?.MessageId ?? -1; } else { @@ -684,13 +685,12 @@ public async Task AcceptPost(Posts post, Users dbUser, CallbackQuery callbackQue var group = new IAlbumInputMedia[attachments.Count]; for (int i = 0; i < attachments.Count; i++) { - MessageType attachmentType = attachments[i].Type; + var attachmentType = attachments[i].Type; if (attachmentType == MessageType.Unknown) { attachmentType = post.PostType; } - group[i] = attachmentType switch - { + group[i] = attachmentType switch { MessageType.Photo => new InputMediaPhoto(new InputFileId(attachments[i].FileID)) { Caption = i == 0 ? postText : null, ParseMode = ParseMode.Html, HasSpoiler = hasSpoiler }, MessageType.Audio => new InputMediaAudio(new InputFileId(attachments[i].FileID)) { Caption = i == 0 ? postText : null, ParseMode = ParseMode.Html }, MessageType.Video => new InputMediaVideo(new InputFileId(attachments[i].FileID)) { Caption = i == 0 ? postText : null, ParseMode = ParseMode.Html, HasSpoiler = hasSpoiler }, @@ -700,23 +700,24 @@ public async Task AcceptPost(Posts post, Users dbUser, CallbackQuery callbackQue }; } - string? warnText = _tagRepository.GetActivedTagWarnings(post.NewTags); + string? warnText = _tagRepository.GetActivedTagWarnings(post.Tags); if (!string.IsNullOrEmpty(warnText)) { await _botClient.SendTextMessageAsync(_channelService.AcceptChannel.Id, warnText, allowSendingWithoutReply: true); } - var messages = await _botClient.SendMediaGroupAsync(_channelService.AcceptChannel.Id, group); - post.PublicMsgID = messages.First().MessageId; + var postMessages = await _botClient.SendMediaGroupAsync(_channelService.AcceptChannel.Id, group); + post.PublicMsgID = postMessages.First().MessageId; + post.PublishMediaGroupID = postMessages.First().MediaGroupId ?? ""; //记录媒体组消息 - await _mediaGroupService.AddPostMediaGroup(messages); + await _mediaGroupService.AddPostMediaGroup(postMessages); } await _botClient.AutoReplyAsync("稿件已发布", callbackQuery); post.ReviewerUID = dbUser.UserID; - post.Status = PostStatus.Accepted; + post.Status = EPostStatus.Accepted; post.ModifyAt = DateTime.Now; //修改审核群消息 @@ -732,18 +733,20 @@ public async Task AcceptPost(Posts post, Users dbUser, CallbackQuery callbackQue post.ReviewMsgID = msg.MessageId; } - await Updateable(post).UpdateColumns(x => new { x.ReviewMsgID, x.PublicMsgID, x.ReviewerUID, x.Status, x.ModifyAt }).ExecuteCommandAsync(); + await Updateable(post).UpdateColumns(x => new { x.ReviewMsgID, x.PublicMsgID, x.PublishMediaGroupID, x.ReviewerUID, x.Status, x.ModifyAt }).ExecuteCommandAsync(); //通知投稿人 string posterMsg = _textHelperService.MakeNotification(post.IsDirectPost, post.PublicMsgID); if (poster.Notification && poster.UserID != dbUser.UserID)//启用通知并且审核与投稿不是同一个人 - {//单独发送通知消息 + { + //单独发送通知消息 await _botClient.SendTextMessageAsync(post.OriginChatID, posterMsg, parseMode: ParseMode.Html, replyToMessageId: (int)post.OriginMsgID, allowSendingWithoutReply: true, disableWebPagePreview: true); } else - {//静默模式, 不单独发送通知消息 - await _botClient.EditMessageTextAsync(post.OriginChatID, (int)post.ActionMsgID, posterMsg, ParseMode.Html, disableWebPagePreview: true); + { + //静默模式, 不单独发送通知消息 + await _botClient.EditMessageTextAsync(post.OriginChatID, (int)post.OriginActionMsgID, posterMsg, ParseMode.Html, disableWebPagePreview: true); } //增加通过数量 @@ -768,7 +771,7 @@ public async Task AcceptPost(Posts post, Users dbUser, CallbackQuery callbackQue } } - public async Task FetchPostFromReplyToMessage(Message message) + public async Task FetchPostFromReplyToMessage(Message message) { var replyMessage = message.ReplyToMessage; if (replyMessage == null) @@ -776,41 +779,34 @@ public async Task AcceptPost(Posts post, Users dbUser, CallbackQuery callbackQue return null; } - Posts? post; + NewPosts? post; - var mediaGroup = await _mediaGroupService.QueryMediaGroup(replyMessage); - if (mediaGroup == null) + var msgGroupId = message.MediaGroupId; + if (string.IsNullOrEmpty(msgGroupId)) { //单条稿件 + long chatId = replyMessage.Chat.Id; int msgId = replyMessage.MessageId; - post = await Queryable().FirstAsync(x => x.ReviewMsgID == msgId || x.ManageMsgID == msgId); + post = await Queryable().FirstAsync(x => + (x.OriginChatID == chatId && x.OriginMsgID == msgId) || (x.OriginActionChatID == chatId && x.OriginActionMsgID == msgId) || + (x.ReviewChatID == chatId && x.ReviewMsgID == msgId) || (x.ReviewActionChatID == chatId && x.ReviewActionMsgID == msgId) + ); } else { - post = await Queryable().FirstAsync(x => x.MediaGroupID == mediaGroup.MediaGroupID); + post = await Queryable().FirstAsync(x => x.OriginMediaGroupID == msgGroupId || x.ReviewMediaGroupID == msgGroupId); } return post; } - public async Task FetchPostFromReviewCallbackQuery(CallbackQuery query) + public async Task FetchPostFromCallbackQuery(CallbackQuery query) { if (query.Message == null) { return null; } - var post = await GetFirstAsync(x => x.ManageMsgID == query.Message.MessageId); - return post; - } - - public async Task FetchPostFromConfirmCallbackQuery(CallbackQuery query) - { - if (query.Message == null) - { - return null; - } - - var post = await GetFirstAsync(x => x.ActionMsgID == query.Message.MessageId); + var post = await FetchPostFromReplyToMessage(query.Message); return post; } } diff --git a/XinjingdailyBot.Service/Data/UserService.cs b/XinjingdailyBot.Service/Data/UserService.cs index e1b7f4c9..aee9ae21 100644 --- a/XinjingdailyBot.Service/Data/UserService.cs +++ b/XinjingdailyBot.Service/Data/UserService.cs @@ -1,7 +1,7 @@ -using System.Text; -using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using SqlSugar; +using System.Text; using Telegram.Bot; using Telegram.Bot.Types; using Telegram.Bot.Types.Enums; @@ -31,6 +31,7 @@ public sealed class UserService : BaseService, IUserService private readonly ITelegramBotClient _botClient; private readonly LevelRepository _levelRepository; private readonly INameHistoryService _nameHistoryService; + private readonly IMediaGroupService _mediaGroupService; public UserService( ILogger logger, @@ -42,7 +43,8 @@ public UserService( PostRepository postRepository, ITelegramBotClient botClient, LevelRepository levelRepository, - INameHistoryService nameHistoryService) + INameHistoryService nameHistoryService, + IMediaGroupService mediaGroupService) { _logger = logger; _optionsSetting = configuration.Value; @@ -54,6 +56,7 @@ public UserService( _botClient = botClient; _levelRepository = levelRepository; _nameHistoryService = nameHistoryService; + _mediaGroupService = mediaGroupService; } /// @@ -63,8 +66,7 @@ public UserService( public async Task FetchUserFromUpdate(Update update) { - var msgChat = update.Type switch - { + var msgChat = update.Type switch { UpdateType.ChannelPost => update.ChannelPost!.Chat, UpdateType.EditedChannelPost => update.EditedChannelPost!.Chat, UpdateType.Message => update.Message!.Chat, @@ -88,8 +90,7 @@ public UserService( } else { - var msgUser = update.Type switch - { + var msgUser = update.Type switch { UpdateType.ChannelPost => update.ChannelPost!.From, UpdateType.EditedChannelPost => update.EditedChannelPost!.From, UpdateType.Message => update.Message!.From, @@ -187,8 +188,7 @@ private async Task AutoLeaveChat(Chat? msgChat) return null; } - dbUser = new() - { + dbUser = new() { UserID = msgUser.Id, UserName = msgUser.Username ?? "", FirstName = msgUser.FirstName, @@ -271,8 +271,7 @@ private async Task AutoLeaveChat(Chat? msgChat) try { dbUser.ModifyAt = DateTime.Now; - await Updateable(dbUser).UpdateColumns(x => new - { + await Updateable(dbUser).UpdateColumns(x => new { x.UserName, x.FirstName, x.LastName, @@ -427,27 +426,26 @@ private async Task AutoDeleteNotification(Message message) //被回复的消息是Bot发的消息 if (replyToMsg.From.Id == _channelService.BotUser.Id) { + var chatId = message.Chat.Id; + var msgId = replyToMsg.MessageId; + //在审核群内 - if (message.Chat.Id == _channelService.ReviewGroup.Id) + if (chatId == _channelService.ReviewGroup.Id) { - var msgID = replyToMsg.MessageId; - - var exp = Expressionable.Create(); - exp.Or(x => x.ManageMsgID == msgID); + NewPosts? post; - if (string.IsNullOrEmpty(replyToMsg.MediaGroupId)) + var mediaGroup = await _mediaGroupService.QueryMediaGroup(chatId, msgId); + if (mediaGroup == null)//单条稿件 { - //普通消息 - exp.Or(x => x.ReviewMsgID == msgID); + post = await _postRepository.Queryable().FirstAsync(x => + (x.ReviewChatID == chatId && x.ReviewMsgID == msgId) || (x.ReviewActionChatID == chatId && x.ReviewActionMsgID == msgId) + ); } - else + else //媒体组稿件 { - //媒体组消息 - exp.Or(x => x.ReviewMsgID <= msgID && x.ManageMsgID > msgID); + post = await _postRepository.Queryable().FirstAsync(x => x.ReviewChatID == chatId && x.ReviewMediaGroupID == mediaGroup.MediaGroupID); } - var post = await _postRepository.Queryable().FirstAsync(exp.ToExpression()); - //判断是不是审核相关消息 if (post != null) { @@ -492,7 +490,7 @@ private async Task AutoDeleteNotification(Message message) return await FetchUserByUserName(target); } } - + public async Task<(string, InlineKeyboardMarkup?)> QueryUserList(Users dbUser, string query, int page) { //每页数量 diff --git a/XinjingdailyBot.Service/Helper/HttpHelperService.cs b/XinjingdailyBot.Service/Helper/HttpHelperService.cs index a4d5af6a..e9681837 100644 --- a/XinjingdailyBot.Service/Helper/HttpHelperService.cs +++ b/XinjingdailyBot.Service/Helper/HttpHelperService.cs @@ -1,6 +1,6 @@ -using System.Net; +using Microsoft.Extensions.Logging; +using System.Net; using System.Text.Json; -using Microsoft.Extensions.Logging; using XinjingdailyBot.Infrastructure.Attribute; using XinjingdailyBot.Infrastructure.Model; using XinjingdailyBot.Interface.Helper; @@ -87,7 +87,7 @@ public HttpHelperService( { HttpRequestMessage request = new(HttpMethod.Get, $"/{ip}"); using var rawResponse = await SendRequestToStream("IpInfo", request); - if(rawResponse==null) + if (rawResponse == null) { return null; } diff --git a/XinjingdailyBot.Service/Helper/MarkupHelperService.cs b/XinjingdailyBot.Service/Helper/MarkupHelperService.cs index 57ed1400..745fc05a 100644 --- a/XinjingdailyBot.Service/Helper/MarkupHelperService.cs +++ b/XinjingdailyBot.Service/Helper/MarkupHelperService.cs @@ -1,6 +1,4 @@ -using System.Threading.Channels; -using Telegram.Bot.Types.Enums; -using Telegram.Bot.Types.ReplyMarkups; +using Telegram.Bot.Types.ReplyMarkups; using XinjingdailyBot.Infrastructure.Attribute; using XinjingdailyBot.Infrastructure.Enums; using XinjingdailyBot.Infrastructure.Extensions; @@ -18,18 +16,22 @@ public sealed class MarkupHelperService : IMarkupHelperService private readonly GroupRepository _groupRepository; private readonly IChannelService _channelService; private readonly TagRepository _tagRepository; + private readonly RejectReasonRepository _rejectReasonRepository; public MarkupHelperService( GroupRepository groupRepository, IChannelService channelService, - TagRepository tagRepository) + TagRepository tagRepository, + RejectReasonRepository rejectReasonRepository) { _groupRepository = groupRepository; _channelService = channelService; _tagRepository = tagRepository; + _rejectReasonRepository = rejectReasonRepository; } public InlineKeyboardMarkup PostKeyboard(bool anymouse) + { InlineKeyboardMarkup keyboard = new(new[] { @@ -98,18 +100,17 @@ public InlineKeyboardMarkup ReviewKeyboardA(int tagNum, bool? hasSpoiler) { var tags = _tagRepository.GetTagsPayload(tagNum); - List> btns = new(); - List line = new(); - int lineCount = tags.Count() <= 4 ? 2 : 3; + var btns = new List>(); + var line = new List(); foreach (var tag in tags) { line.Add(InlineKeyboardButton.WithCallbackData(tag.DisplayName, $"review tag {tag.Payload}")); if (line.Count >= lineCount) { btns.Add(line); - line = new(); + line = new List(); } } @@ -132,32 +133,33 @@ public InlineKeyboardMarkup ReviewKeyboardA(int tagNum, bool? hasSpoiler) InlineKeyboardButton.WithCallbackData(Langs.ReviewAccept, "review accept"), }); - return new(btns); + return new InlineKeyboardMarkup(btns); } public InlineKeyboardMarkup ReviewKeyboardB() { - InlineKeyboardMarkup keyboard = new(new[] + var reasons = _rejectReasonRepository.GetAllRejectReasons(); + + int lineCount = reasons.Count() <= 4 ? 2 : 3; + + var btns = new List>(); + var line = new List(); + foreach (var reason in reasons) { - new [] - { - InlineKeyboardButton.WithCallbackData(Langs.RejectFuzzy, "reject fuzzy"), - InlineKeyboardButton.WithCallbackData(Langs.RejectDuplicate, "reject duplicate"), - InlineKeyboardButton.WithCallbackData(Langs.RejectBoring, "reject boring"), - InlineKeyboardButton.WithCallbackData(Langs.RejectConfusing, "reject confusing"), - }, - new [] - { - InlineKeyboardButton.WithCallbackData(Langs.RejectDeny, "reject deny"), - InlineKeyboardButton.WithCallbackData(Langs.RejectQRCode, "reject qrcode"), - InlineKeyboardButton.WithCallbackData(Langs.RejectOther, "reject other"), - }, - new [] + line.Add(InlineKeyboardButton.WithCallbackData(reason.Name, $"review tag {reason.Payload}")); + if (line.Count >= lineCount) { - InlineKeyboardButton.WithCallbackData(Langs.RejectCancel, "reject back"), - }, + btns.Add(line); + line = new List(); + } + } + + btns.Add(new[] + { + InlineKeyboardButton.WithCallbackData(Langs.RejectCancel, "review reject back"), }); - return keyboard; + + return new InlineKeyboardMarkup(btns); } public async Task SetUserGroupKeyboard(Users dbUser, Users targetUser) @@ -272,7 +274,7 @@ public InlineKeyboardMarkup ReviewKeyboardB() return keyboard; } - public InlineKeyboardMarkup? LinkToOriginPostKeyboard(Posts post) + public InlineKeyboardMarkup? LinkToOriginPostKeyboard(NewPosts post) { var channel = _channelService.AcceptChannel; string link = channel.GetMessageLink(post.PublicMsgID); @@ -369,7 +371,7 @@ public InlineKeyboardMarkup RandomPostMenuKeyboard(Users dbUser, int tagNum) return keyboard; } - public InlineKeyboardMarkup RandomPostMenuKeyboard(Users dbUser, Posts post, int tagId, string postType) + public InlineKeyboardMarkup RandomPostMenuKeyboard(Users dbUser, NewPosts post, int tagId, string postType) { var channel = _channelService.AcceptChannel; string link = channel.GetMessageLink(post.PublicMsgID); @@ -386,11 +388,11 @@ public InlineKeyboardMarkup RandomPostMenuKeyboard(Users dbUser, Posts post, int return keyboard; } - public InlineKeyboardMarkup QueryPostMenuKeyboard(Users dbUser, Posts post) + public InlineKeyboardMarkup QueryPostMenuKeyboard(Users dbUser, NewPosts post) { InlineKeyboardMarkup keyboard; - if (post.Status == PostStatus.Accepted) + if (post.Status == EPostStatus.Accepted) { keyboard = new(new[] { diff --git a/XinjingdailyBot.Service/Helper/TextHelperService.cs b/XinjingdailyBot.Service/Helper/TextHelperService.cs index 0e8cb5a7..5540a1a5 100644 --- a/XinjingdailyBot.Service/Helper/TextHelperService.cs +++ b/XinjingdailyBot.Service/Helper/TextHelperService.cs @@ -1,11 +1,9 @@ -using System.Text; -using System.Text.RegularExpressions; -using Microsoft.Extensions.Options; +using Microsoft.Extensions.Options; +using System.Text; using Telegram.Bot.Types; using Telegram.Bot.Types.Enums; using XinjingdailyBot.Infrastructure; using XinjingdailyBot.Infrastructure.Attribute; -using XinjingdailyBot.Infrastructure.Enums; using XinjingdailyBot.Infrastructure.Model; using XinjingdailyBot.Interface.Bot.Common; using XinjingdailyBot.Interface.Helper; @@ -38,9 +36,6 @@ public TextHelperService( private bool PureReturns { get; init; } private bool PureHashTag { get; init; } - private static readonly Regex MatchTag = new(@"(^#\S+)|(\s#\S+)"); - private static readonly Regex MatchSpace = new(@"^\s*$"); - public string PureText(string? text) { if (string.IsNullOrEmpty(text)) @@ -51,13 +46,14 @@ public string PureText(string? text) if (PureHashTag) { //过滤HashTag - text = MatchTag.Replace(text, ""); + text = RegexUtils.MatchHashTag().Replace(text, ""); } if (PureReturns) { + var matchSpace = RegexUtils.MatchBlankLine(); //过滤连续换行 - var parts = text.Split('\n', StringSplitOptions.RemoveEmptyEntries).Where(x => !MatchSpace.IsMatch(x)).Select(x => x.Trim()); + var parts = text.Split('\n', StringSplitOptions.RemoveEmptyEntries).Where(x => !matchSpace.IsMatch(x)).Select(x => x.Trim()); text = string.Join('\n', parts); } @@ -156,24 +152,6 @@ public string MakeReviewMessage(Users poster, Users reviewer, bool anymouse, str return msg; } - public string RejectReasonToString(RejectReason rejectReason) - { - var reason = rejectReason switch - { - RejectReason.Fuzzy => "图片模糊/看不清", - RejectReason.Duplicate => "重复的稿件", - RejectReason.Boring => "内容不够有趣", - RejectReason.Confused => "审核没看懂,建议配文说明", - RejectReason.Deny => "不合适发布的内容", - RejectReason.QRCode => "稿件包含二维码水印", - RejectReason.Other => "其他原因", - RejectReason.CustomReason => "其他原因", - RejectReason.AutoReject => "稿件审核超时, 自动拒绝", - _ => "未知", - }; - return reason; - } - public string MakeNotification(bool isDirect, long messageID) { var msgLink = HtmlMessageLink(messageID, _channelService.AcceptChannel.Username ?? _channelService.AcceptChannel.Id.ToString(), "消息直链"); @@ -187,13 +165,13 @@ public string MakeNotification(string reason) return msg; } - public string MakePoster(Posts post, Users poster) + public string MakePoster(NewPosts post, Users poster, ChannelOptions? channel) { var user = HtmlUserLink(poster); - if (post.IsFromChannel) + if (post.IsFromChannel && !string.IsNullOrEmpty(channel?.ChannelName)) { - var channel = HtmlUserLink(0, post.ChannelName, post.ChannelTitle); + var link = HtmlMessageLink(post.ChannelMsgId, channel.ChannelTitle, channel.ChannelName); if (post.Anonymous) { return $"from {channel}"; @@ -216,9 +194,9 @@ public string MakePoster(Posts post, Users poster) } } - public string MakePostText(Posts post, Users poster) + public string MakePostText(NewPosts post, Users poster, ChannelOptions? channel) { - var tag = _tagRepository.GetActiviedHashTags(post.NewTags); + var tag = _tagRepository.GetActiviedHashTags(post.Tags); StringBuilder sb = new(); @@ -233,7 +211,7 @@ public string MakePostText(Posts post, Users poster) sb.AppendLine(text); } - var from = MakePoster(post, poster); + var from = MakePoster(post, poster, channel); if (sb.Length > 0) { diff --git a/XinjingdailyBot.Service/XinjingdailyBot.Service.csproj b/XinjingdailyBot.Service/XinjingdailyBot.Service.csproj index c28d6143..e4c58094 100644 --- a/XinjingdailyBot.Service/XinjingdailyBot.Service.csproj +++ b/XinjingdailyBot.Service/XinjingdailyBot.Service.csproj @@ -1,19 +1,23 @@  - - Library - + + Library + - - - - + + + + - - - - - - + + + + + + + + + + diff --git a/XinjingdailyBot.Tasks/ExpiredPostsTask.cs b/XinjingdailyBot.Tasks/ExpiredPostsTask.cs index 0823dd54..79fe7118 100644 --- a/XinjingdailyBot.Tasks/ExpiredPostsTask.cs +++ b/XinjingdailyBot.Tasks/ExpiredPostsTask.cs @@ -1,6 +1,6 @@ -using System.Text; -using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; +using System.Text; using Telegram.Bot; using Telegram.Bot.Types.Enums; using XinjingdailyBot.Infrastructure; @@ -48,7 +48,7 @@ public async Task Execute(IJobExecutionContext context) //获取有过期稿件的用户 var userIDList = await _postService.Queryable() - .Where(x => (x.Status == PostStatus.Padding || x.Status == PostStatus.Reviewing) && x.ModifyAt < expiredDate) + .Where(x => (x.Status == EPostStatus.Padding || x.Status == EPostStatus.Reviewing) && x.ModifyAt < expiredDate) .Distinct().Select(x => x.PosterUID).ToListAsync(); if (!userIDList.Any()) @@ -63,7 +63,7 @@ public async Task Execute(IJobExecutionContext context) { //获取过期投稿 var paddingPosts = await _postService.Queryable() - .Where(x => x.PosterUID == userID && (x.Status == PostStatus.Padding || x.Status == PostStatus.Reviewing) && x.ModifyAt < expiredDate) + .Where(x => x.PosterUID == userID && (x.Status == EPostStatus.Padding || x.Status == EPostStatus.Reviewing) && x.ModifyAt < expiredDate) .ToListAsync(); if (!paddingPosts.Any()) @@ -74,14 +74,14 @@ public async Task Execute(IJobExecutionContext context) int cTmout = 0, rTmout = 0; foreach (var post in paddingPosts) { - if (post.Status == PostStatus.Padding) + if (post.Status == EPostStatus.Padding) { - post.Status = PostStatus.ConfirmTimeout; + post.Status = EPostStatus.ConfirmTimeout; cTmout++; } else { - post.Status = PostStatus.ReviewTimeout; + post.Status = EPostStatus.ReviewTimeout; rTmout++; } post.ModifyAt = DateTime.Now; diff --git a/XinjingdailyBot.Tasks/PostAdvertiseTask.cs b/XinjingdailyBot.Tasks/PostAdvertiseTask.cs index e7a3ee1c..7972e877 100644 --- a/XinjingdailyBot.Tasks/PostAdvertiseTask.cs +++ b/XinjingdailyBot.Tasks/PostAdvertiseTask.cs @@ -12,7 +12,7 @@ namespace XinjingdailyBot.Tasks /// /// 发布广告 /// - [Job("0 0 19 * * ?")] + [Job("0 0 9 * * ?")] public class PostAdvertiseTask : IJob { private readonly ILogger _logger; @@ -51,13 +51,13 @@ public async Task Execute(IJobExecutionContext context) return; } - var operates = new List<(AdMode, ChatId)> + var operates = new List<(EAdMode, ChatId)> { - new (AdMode.AcceptChannel, channelService.AcceptChannel.Id), - new (AdMode.RejectChannel, channelService.RejectChannel.Id), - new (AdMode.ReviewGroup, channelService.ReviewGroup.Id), - new (AdMode.CommentGroup, channelService.CommentGroup.Id), - new (AdMode.SubGroup, channelService.SubGroup.Id), + new (EAdMode.AcceptChannel, channelService.AcceptChannel.Id), + new (EAdMode.RejectChannel, channelService.RejectChannel.Id), + new (EAdMode.ReviewGroup, channelService.ReviewGroup.Id), + new (EAdMode.CommentGroup, channelService.CommentGroup.Id), + new (EAdMode.SubGroup, channelService.SubGroup.Id), }; foreach (var (mode, chatId) in operates) diff --git a/XinjingdailyBot.Tasks/XinjingdailyBot.Tasks.csproj b/XinjingdailyBot.Tasks/XinjingdailyBot.Tasks.csproj index a216ce34..c8d529ee 100644 --- a/XinjingdailyBot.Tasks/XinjingdailyBot.Tasks.csproj +++ b/XinjingdailyBot.Tasks/XinjingdailyBot.Tasks.csproj @@ -1,24 +1,28 @@  - - Library - + + Library + - - - - - - - + + + + + + + - - - - + + + - - - + + + + + + + + diff --git a/XinjingdailyBot.WebAPI/Extensions/DatabaseExtension.cs b/XinjingdailyBot.WebAPI/Extensions/DatabaseExtension.cs index 4dba7431..69b70d3b 100644 --- a/XinjingdailyBot.WebAPI/Extensions/DatabaseExtension.cs +++ b/XinjingdailyBot.WebAPI/Extensions/DatabaseExtension.cs @@ -1,7 +1,7 @@ -using System.Diagnostics.CodeAnalysis; -using System.Reflection; -using SqlSugar; +using SqlSugar; using SqlSugar.IOC; +using System.Diagnostics.CodeAnalysis; +using System.Reflection; using XinjingdailyBot.Infrastructure; namespace XinjingdailyBot.WebAPI.Extensions @@ -34,30 +34,28 @@ public static void AddSqlSugar(this IServiceCollection services, IConfiguration Environment.Exit(1); } + _logger.Info("数据库驱动: {0}",dbConfig.UseMySQL?"MySQL":"SQLite"); + string connStr = dbConfig.UseMySQL ? $"Host={dbConfig.DbHost};Port={dbConfig.DbPort};Database={dbConfig.DbName};UserID={dbConfig.DbUser};Password={dbConfig.DbPassword};CharSet=utf8mb4;AllowZeroDateTime=true" : $"DataSource={dbConfig.DbName}.db"; - services.AddSqlSugar(new IocConfig - { + services.AddSqlSugar(new IocConfig { ConfigId = 0, ConnectionString = connStr, DbType = dbConfig.UseMySQL ? IocDbType.MySql : IocDbType.Sqlite, IsAutoCloseConnection = true//自动释放 }); - SugarIocServices.ConfigurationSugar(db => - { + SugarIocServices.ConfigurationSugar(db => { if (dbConfig.LogSQL) { - db.Aop.OnLogExecuting = (sql, pars) => - { + db.Aop.OnLogExecuting = (sql, pars) => { var param = db.GetConnectionScope(0).Utilities.SerializeObject(pars.ToDictionary(it => it.ParameterName, it => it.Value)); _logger.Debug("{sql},{param}", sql, param); }; - db.Aop.OnError = (e) => - { + db.Aop.OnError = (e) => { _logger.Error("执行SQL出错:", e); }; } @@ -72,7 +70,7 @@ public static void AddSqlSugar(this IServiceCollection services, IConfiguration } //创建数据表 - Assembly assembly = Assembly.Load("XinjingdailyBot.Model"); + var assembly = Assembly.Load("XinjingdailyBot.Model"); var types = assembly.GetTypes() .Where(x => x.GetCustomAttribute() != null); diff --git a/XinjingdailyBot.WebAPI/Extensions/HttpClientExtension.cs b/XinjingdailyBot.WebAPI/Extensions/HttpClientExtension.cs index 360fd23a..0c2f59b1 100644 --- a/XinjingdailyBot.WebAPI/Extensions/HttpClientExtension.cs +++ b/XinjingdailyBot.WebAPI/Extensions/HttpClientExtension.cs @@ -1,6 +1,6 @@ -using System.Net; -using Microsoft.Extensions.Options; +using Microsoft.Extensions.Options; using Microsoft.Net.Http.Headers; +using System.Net; using XinjingdailyBot.Infrastructure; namespace XinjingdailyBot.WebAPI.Extensions @@ -17,15 +17,13 @@ public static class HttpClientExtension /// public static void AddHttpClients(this IServiceCollection services) { - services.AddHttpClient("Telegram", (serviceProvider, httpClient) => - { + services.AddHttpClient("Telegram", (serviceProvider, httpClient) => { var config = serviceProvider.GetRequiredService>().Value; string? baseUrl = config.Bot.BaseUrl; httpClient.BaseAddress = new Uri(baseUrl ?? "https://api.telegram.org/"); httpClient.DefaultRequestHeaders.Add(HeaderNames.Accept, "application/json"); httpClient.DefaultRequestHeaders.Add(HeaderNames.UserAgent, nameof(XinjingdailyBot)); - }).ConfigurePrimaryHttpMessageHandler(serviceProvider => - { + }).ConfigurePrimaryHttpMessageHandler(serviceProvider => { var config = serviceProvider.GetRequiredService>().Value; string? proxy = config.Bot.Proxy; @@ -35,15 +33,13 @@ public static void AddHttpClients(this IServiceCollection services) _logger.Info("已配置代理: {0}", proxy); tgProxy = new WebProxy { Address = new Uri(proxy) }; } - return new HttpClientHandler - { + return new HttpClientHandler { Proxy = tgProxy, UseProxy = tgProxy != null, }; }); - services.AddHttpClient("GitHub", (serviceProvider, httpClient) => - { + services.AddHttpClient("GitHub", (serviceProvider, httpClient) => { var config = serviceProvider.GetRequiredService>().Value; string? baseUrl = config.GitHub.BaseUrl; httpClient.BaseAddress = new Uri(baseUrl ?? "https://hub.chrxw.com/"); @@ -51,8 +47,7 @@ public static void AddHttpClients(this IServiceCollection services) httpClient.DefaultRequestHeaders.Add(HeaderNames.UserAgent, nameof(XinjingdailyBot)); }); - services.AddHttpClient("IpInfo", (serviceProvider, httpClient) => - { + services.AddHttpClient("IpInfo", (serviceProvider, httpClient) => { var config = serviceProvider.GetRequiredService>().Value; httpClient.BaseAddress = new Uri("https://ipinfo.io/"); httpClient.DefaultRequestHeaders.Add(HeaderNames.Accept, "application/json"); diff --git a/XinjingdailyBot.WebAPI/Extensions/SwaggerExtension.cs b/XinjingdailyBot.WebAPI/Extensions/SwaggerExtension.cs index 4ad0ecc4..a2fb039f 100644 --- a/XinjingdailyBot.WebAPI/Extensions/SwaggerExtension.cs +++ b/XinjingdailyBot.WebAPI/Extensions/SwaggerExtension.cs @@ -14,21 +14,17 @@ public static class SwaggerExtension public static void AddSwagger(this IServiceCollection services) { services.AddEndpointsApiExplorer(); - services.AddSwaggerGen(options => - { - options.SwaggerDoc("v1", new OpenApiInfo - { + services.AddSwaggerGen(options => { + options.SwaggerDoc("v1", new OpenApiInfo { Version = "v1", Title = "XinjingdailyBot API", Description = "An ASP.NET Core Web API for managing ToDo items", TermsOfService = new Uri("https://example.com/terms"), - Contact = new OpenApiContact - { + Contact = new OpenApiContact { Name = "Example Contact", Url = new Uri("https://example.com/contact") }, - License = new OpenApiLicense - { + License = new OpenApiLicense { Name = "Example License", Url = new Uri("https://example.com/license") }, diff --git a/XinjingdailyBot.WebAPI/Extensions/TaskExtension.cs b/XinjingdailyBot.WebAPI/Extensions/TaskExtension.cs index 88196fcd..79d7b662 100644 --- a/XinjingdailyBot.WebAPI/Extensions/TaskExtension.cs +++ b/XinjingdailyBot.WebAPI/Extensions/TaskExtension.cs @@ -1,6 +1,6 @@ -using System.Diagnostics.CodeAnalysis; +using Quartz; +using System.Diagnostics.CodeAnalysis; using System.Reflection; -using Quartz; using XinjingdailyBot.Infrastructure.Attribute; namespace XinjingdailyBot.WebAPI.Extensions @@ -25,8 +25,7 @@ public static void AddTasks(this IServiceCollection services) return; } - services.AddQuartz(qz => - { + services.AddQuartz(qz => { qz.UseMicrosoftDependencyInjectionJobFactory(); _logger.Debug($"===== 注册定时任务 ====="); @@ -53,8 +52,7 @@ public static void AddTasks(this IServiceCollection services) _logger.Debug($"===== 注册了 {count} 定时任务 ====="); }); - services.AddQuartzServer(op => - { + services.AddQuartzServer(op => { op.StartDelay = TimeSpan.FromSeconds(10); op.AwaitApplicationStarted = true; op.WaitForJobsToComplete = true; diff --git a/XinjingdailyBot.WebAPI/Extensions/TelegramExtension.cs b/XinjingdailyBot.WebAPI/Extensions/TelegramExtension.cs index b0b34f78..463ea725 100644 --- a/XinjingdailyBot.WebAPI/Extensions/TelegramExtension.cs +++ b/XinjingdailyBot.WebAPI/Extensions/TelegramExtension.cs @@ -17,8 +17,7 @@ public static class TelegramExtension /// public static void AddTelegramBotClient(this IServiceCollection services) { - services.AddSingleton(serviceProvider => - { + services.AddSingleton(serviceProvider => { var httpClientFactory = serviceProvider.GetRequiredService(); var httpClient = httpClientFactory.CreateClient("Telegram"); diff --git a/XinjingdailyBot.WebAPI/Program.cs b/XinjingdailyBot.WebAPI/Program.cs index 125323bd..9ef56565 100644 --- a/XinjingdailyBot.WebAPI/Program.cs +++ b/XinjingdailyBot.WebAPI/Program.cs @@ -1,7 +1,8 @@  -using System.Diagnostics.CodeAnalysis; using NLog.Extensions.Logging; +using System.Diagnostics.CodeAnalysis; using XinjingdailyBot.Infrastructure; +using XinjingdailyBot.Infrastructure.Localization; using XinjingdailyBot.WebAPI.Extensions; namespace XinjingdailyBot.WebAPI @@ -20,7 +21,15 @@ public static class Program [RequiresUnreferencedCode("不兼容剪裁")] public static void Main(string[] args) { - _logger.Info("欢迎使用 XinjingdailyBot Version: {0} - {1}", Utils.Version, BuildInfo.Variant); + _logger.Info(Langs.Line); + _logger.Info("欢迎使用 XinjingdailyBot"); + _logger.Info(Langs.Version, Utils.Version, BuildInfo.Variant); + _logger.Info(Langs.Copyright, BuildInfo.Author); + _logger.Info(Langs.Line); + _logger.Warn("欢迎订阅心惊报 https://t.me/xinjingdaily"); + _logger.Info(Langs.Line); + + Thread.Sleep(2000); var builder = WebApplication.CreateBuilder(args); @@ -28,8 +37,7 @@ public static void Main(string[] args) builder.Services.AddOptions().Configure(builder.Configuration); //NLog - builder.Services.AddLogging(loggingBuilder => - { + builder.Services.AddLogging(loggingBuilder => { loggingBuilder.ClearProviders(); loggingBuilder.SetMinimumLevel(LogLevel.Debug); loggingBuilder.AddNLog(); diff --git a/XinjingdailyBot.WebAPI/nlog.config b/XinjingdailyBot.WebAPI/nlog.config index 18547dae..760bf69f 100644 --- a/XinjingdailyBot.WebAPI/nlog.config +++ b/XinjingdailyBot.WebAPI/nlog.config @@ -1,9 +1,9 @@  + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + autoReload="true" + internalLogLevel="Warn" + internalLogFile="${basedir}/logs/nlog-internal.txt"> @@ -18,51 +18,52 @@ + layout="${level:format=FirstCharacter} ${date} [${logger:shortName=true}] ${message}"> - + + errorStream="True" + enableAnsiOutput="True" + layout="${level:format=FirstCharacter} ${date} [${logger:shortName=true}] ${message} ${exception:format=toString,Data}" /> + fileName="${basedir}/logs/log.txt" + archiveFileName="${basedir}/logs/log.${date:format=yyyy-MM-dd}.txt" + archiveEvery="Day" + archiveAboveSize="20000000" + maxArchiveFiles="30" + archiveOldFileOnStartup="true" + keepFileOpen="true" + layout="${longdate} | ${level} | ${logger} | ${message}" /> + fileName="${basedir}/logs/error.txt" + archiveFileName="${basedir}/logs/error.${date:format=yyyy-MM-dd}.txt" + archiveEvery="Day" + archiveAboveSize="20000000" + maxArchiveFiles="30" + archiveOldFileOnStartup="true" + keepFileOpen="true" + layout="${longdate} | ${level} | ${logger} | ${message} | ${exception:format=toString,Data}" /> + fileName="${basedir}/logs/all.txt" + archiveFileName="${basedir}/logs/all.${date:format=yyyy-MM-dd}.txt" + archiveEvery="Day" + archiveAboveSize="20000000" + maxArchiveFiles="30" + archiveOldFileOnStartup="true" + keepFileOpen="true" + layout="${longdate} | ${level} | ${logger} | ${message}" /> @@ -76,14 +77,15 @@ - + - +