فهرست منبع

搜同款支持代理ip

dodo hold 1 سال پیش
والد
کامیت
f8016ea0fc
54فایلهای تغییر یافته به همراه1185 افزوده شده و 243 حذف شده
  1. 231 0
      .editorconfig
  2. 81 2
      molilian.api/Controllers/admin/AliyunController.cs
  3. 51 2
      molilian.api/Controllers/public/ApiController.cs
  4. 340 0
      molilian.api/Controllers/public/FeatureController.cs
  5. 5 15
      molilian.api/Controllers/public/TaskController.cs
  6. 16 6
      molilian.api/Dockerfile
  7. 40 0
      molilian.api/Dockerfile.original
  8. 0 11
      molilian.api/Properties/PublishProfiles/ccr.ccs.tencentyun.com_shaobin.pubxml.user
  9. 0 7
      molilian.api/Properties/PublishProfiles/https___ccr.ccs.tencentyun.com_shaobin.pubxml.user
  10. 0 0
      molilian.api/Properties/PublishProfiles/latest.pubxml
  11. 7 0
      molilian.api/Properties/PublishProfiles/latest.pubxml.user
  12. 1 2
      molilian.api/Properties/PublishProfiles/tester.pubxml
  13. 7 0
      molilian.api/Properties/PublishProfiles/tester.pubxml.user
  14. 1 1
      molilian.api/Properties/launchSettings.json
  15. 1 0
      molilian.api/molilian.api.csproj
  16. 1 1
      molilian.api/molilian.api.csproj.user
  17. 8 0
      molilian.core/Core/NotifyCore.cs
  18. 55 1
      molilian.core/Core/ProxyNodesCore.cs
  19. 12 1
      molilian.core/Core/aliyun/AliyunPoolCore.cs
  20. 2 2
      molilian.core/Core/cps/ElePoolCore.cs
  21. 2 2
      molilian.core/Core/cps/MeituanPoolCore.cs
  22. 1 0
      molilian.core/Core/log/cps.cs
  23. 1 0
      molilian.core/Core/log/dy.cs
  24. 1 0
      molilian.core/Core/log/jd.cs
  25. 1 0
      molilian.core/Core/log/ks.cs
  26. 1 0
      molilian.core/Core/log/pdd.cs
  27. 1 0
      molilian.core/Core/log/promotion.cs
  28. 1 0
      molilian.core/Core/log/taobao.cs
  29. 13 5
      molilian.core/Core/taoke/TaokeOpenCore.cs
  30. 28 26
      molilian.core/Core/taoke/UnionParseCore.cs
  31. 1 0
      molilian.core/DTO/alimama/AlimamaWarningDTO.cs
  32. 1 0
      molilian.core/DTO/alimama/PromotionQueryDTO.cs
  33. 1 0
      molilian.core/DTO/alimama/TkDataDTO.cs
  34. 1 0
      molilian.core/DTO/alimama/UnionCouponDTO.cs
  35. 1 0
      molilian.core/DTO/aliyun/AliyunPoolDTO.cs
  36. 1 0
      molilian.core/DTO/cps/UnionCpsDTO.cs
  37. 1 0
      molilian.core/DTO/dy/DyDataDTO.cs
  38. 1 0
      molilian.core/DTO/jd/JdDataDTO.cs
  39. 1 0
      molilian.core/DTO/ks/KsDataDTO.cs
  40. 1 0
      molilian.core/DTO/pdd/PddDataDTO.cs
  41. 6 6
      molilian.core/Plus/Alimama/orders.cs
  42. 27 5
      molilian.core/Plus/Alimama/parse_2.cs
  43. 1 0
      molilian.core/Plus/JDUnion/EstimateComm.cs
  44. 1 1
      molilian.core/Plus/JDUnion/H5stHack.cs
  45. 1 0
      molilian.core/Plus/JDUnion/SpreadEffect.cs
  46. 1 0
      molilian.core/Plus/JDUnion/amount.cs
  47. 139 139
      molilian.core/Plus/JDUnion/goods.cs
  48. 59 0
      molilian.core/Plus/ProxyManager.cs
  49. 12 4
      molilian.core/Plus/TaobaoOpen/TaobaoOpenPlus.cs
  50. 1 0
      molilian.core/molilian.core.csproj
  51. 5 0
      molilian.sln
  52. 2 1
      nuget.config
  53. 6 0
      taobao-sdk-netcore-auto_1719572210878-20240628-source/DefaultTopClient.cs
  54. 5 3
      taobao-sdk-netcore-auto_1719572210878-20240628-source/Util/WebUtils.cs

+ 231 - 0
.editorconfig

@@ -0,0 +1,231 @@
+# 如果要从更高级别的目录继承 .editorconfig 设置,请删除以下行
+root = true
+
+# c# 文件
+[*.cs]
+
+#### Core EditorConfig 选项 ####
+
+# 缩进和间距
+indent_size = 4
+indent_style = space
+tab_width = 4
+
+# 新行首选项
+end_of_line = crlf
+insert_final_newline = false
+
+#### .NET 编码约定 ####
+
+# 组织 Using
+dotnet_separate_import_directive_groups = false
+dotnet_sort_system_directives_first = false
+file_header_template = unset
+
+# this. 和 Me. 首选项
+dotnet_style_qualification_for_event = false
+dotnet_style_qualification_for_field = false
+dotnet_style_qualification_for_method = false
+dotnet_style_qualification_for_property = false
+
+# 语言关键字与 bcl 类型首选项
+dotnet_style_predefined_type_for_locals_parameters_members = true
+dotnet_style_predefined_type_for_member_access = true
+
+# 括号首选项
+dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity
+dotnet_style_parentheses_in_other_binary_operators = always_for_clarity
+dotnet_style_parentheses_in_other_operators = never_if_unnecessary
+dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity
+
+# 修饰符首选项
+dotnet_style_require_accessibility_modifiers = for_non_interface_members
+
+# 表达式级首选项
+dotnet_style_coalesce_expression = true
+dotnet_style_collection_initializer = true
+dotnet_style_explicit_tuple_names = true
+dotnet_style_namespace_match_folder = true
+dotnet_style_null_propagation = true
+dotnet_style_object_initializer = true
+dotnet_style_operator_placement_when_wrapping = beginning_of_line
+dotnet_style_prefer_auto_properties = true
+dotnet_style_prefer_collection_expression = when_types_loosely_match
+dotnet_style_prefer_compound_assignment = true
+dotnet_style_prefer_conditional_expression_over_assignment = true
+dotnet_style_prefer_conditional_expression_over_return = true
+dotnet_style_prefer_foreach_explicit_cast_in_source = when_strongly_typed
+dotnet_style_prefer_inferred_anonymous_type_member_names = true
+dotnet_style_prefer_inferred_tuple_names = true
+dotnet_style_prefer_is_null_check_over_reference_equality_method = true
+dotnet_style_prefer_simplified_boolean_expressions = true
+dotnet_style_prefer_simplified_interpolation = true
+
+# 字段首选项
+dotnet_style_readonly_field = true
+
+# 参数首选项
+dotnet_code_quality_unused_parameters = all
+
+# 禁止显示首选项
+dotnet_remove_unnecessary_suppression_exclusions = none
+
+# 新行首选项
+dotnet_style_allow_multiple_blank_lines_experimental = true
+dotnet_style_allow_statement_immediately_after_block_experimental = true
+
+#### c# 编码约定 ####
+
+# var 首选项
+csharp_style_var_elsewhere = false
+csharp_style_var_for_built_in_types = false
+csharp_style_var_when_type_is_apparent = false
+
+# Expression-bodied 成员
+csharp_style_expression_bodied_accessors = true
+csharp_style_expression_bodied_constructors = false
+csharp_style_expression_bodied_indexers = true
+csharp_style_expression_bodied_lambdas = true
+csharp_style_expression_bodied_local_functions = false
+csharp_style_expression_bodied_methods = false
+csharp_style_expression_bodied_operators = false
+csharp_style_expression_bodied_properties = true
+
+# 模式匹配首选项
+csharp_style_pattern_matching_over_as_with_null_check = true
+csharp_style_pattern_matching_over_is_with_cast_check = true
+csharp_style_prefer_extended_property_pattern = true
+csharp_style_prefer_not_pattern = true
+csharp_style_prefer_pattern_matching = true
+csharp_style_prefer_switch_expression = true
+
+# Null 检查首选项
+csharp_style_conditional_delegate_call = true
+
+# 修饰符首选项
+csharp_prefer_static_local_function = true
+csharp_preferred_modifier_order = public,private,protected,internal,file,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,required,volatile,async
+csharp_style_prefer_readonly_struct = true
+csharp_style_prefer_readonly_struct_member = true
+
+# 代码块首选项
+csharp_prefer_braces = true
+csharp_prefer_simple_using_statement = true
+csharp_style_namespace_declarations = block_scoped
+csharp_style_prefer_method_group_conversion = true
+csharp_style_prefer_primary_constructors = true
+csharp_style_prefer_top_level_statements = true
+
+# 表达式级首选项
+csharp_prefer_simple_default_expression = true
+csharp_style_deconstructed_variable_declaration = true
+csharp_style_implicit_object_creation_when_type_is_apparent = true
+csharp_style_inlined_variable_declaration = true
+csharp_style_prefer_index_operator = true
+csharp_style_prefer_local_over_anonymous_function = true
+csharp_style_prefer_null_check_over_type_check = true
+csharp_style_prefer_range_operator = true
+csharp_style_prefer_tuple_swap = true
+csharp_style_prefer_utf8_string_literals = true
+csharp_style_throw_expression = true
+csharp_style_unused_value_assignment_preference = discard_variable
+csharp_style_unused_value_expression_statement_preference = discard_variable
+
+# "using" 指令首选项
+csharp_using_directive_placement = outside_namespace
+
+# 新行首选项
+csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = true
+csharp_style_allow_blank_line_after_token_in_arrow_expression_clause_experimental = true
+csharp_style_allow_blank_line_after_token_in_conditional_expression_experimental = true
+csharp_style_allow_blank_lines_between_consecutive_braces_experimental = true
+csharp_style_allow_embedded_statements_on_same_line_experimental = true
+
+#### C# 格式规则 ####
+
+# 新行首选项
+csharp_new_line_before_catch = true
+csharp_new_line_before_else = true
+csharp_new_line_before_finally = true
+csharp_new_line_before_members_in_anonymous_types = true
+csharp_new_line_before_members_in_object_initializers = true
+csharp_new_line_before_open_brace = all
+csharp_new_line_between_query_expression_clauses = true
+
+# 缩进首选项
+csharp_indent_block_contents = true
+csharp_indent_braces = false
+csharp_indent_case_contents = true
+csharp_indent_case_contents_when_block = true
+csharp_indent_labels = no_change
+csharp_indent_switch_labels = true
+
+# 空格键首选项
+csharp_space_after_cast = false
+csharp_space_after_colon_in_inheritance_clause = true
+csharp_space_after_comma = true
+csharp_space_after_dot = false
+csharp_space_after_keywords_in_control_flow_statements = true
+csharp_space_after_semicolon_in_for_statement = true
+csharp_space_around_binary_operators = before_and_after
+csharp_space_around_declaration_statements = false
+csharp_space_before_colon_in_inheritance_clause = true
+csharp_space_before_comma = false
+csharp_space_before_dot = false
+csharp_space_before_open_square_brackets = false
+csharp_space_before_semicolon_in_for_statement = false
+csharp_space_between_empty_square_brackets = false
+csharp_space_between_method_call_empty_parameter_list_parentheses = false
+csharp_space_between_method_call_name_and_opening_parenthesis = false
+csharp_space_between_method_call_parameter_list_parentheses = false
+csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
+csharp_space_between_method_declaration_name_and_open_parenthesis = false
+csharp_space_between_method_declaration_parameter_list_parentheses = false
+csharp_space_between_parentheses = false
+csharp_space_between_square_brackets = false
+
+# 包装首选项
+csharp_preserve_single_line_blocks = true
+csharp_preserve_single_line_statements = true
+
+#### 命名样式 ####
+
+# 命名规则
+
+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.pascal_case.required_prefix = 
+dotnet_naming_style.pascal_case.required_suffix = 
+dotnet_naming_style.pascal_case.word_separator = 
+dotnet_naming_style.pascal_case.capitalization = pascal_case
+
+dotnet_naming_style.begins_with_i.required_prefix = I
+dotnet_naming_style.begins_with_i.required_suffix = 
+dotnet_naming_style.begins_with_i.word_separator = 
+dotnet_naming_style.begins_with_i.capitalization = pascal_case

+ 81 - 2
molilian.api/Controllers/admin/AliyunController.cs

@@ -38,7 +38,7 @@ namespace molilian.api.Controllers
             {
                 filter += $" AND (name like @keyword OR username like @keyword OR company like @keyword OR mobile like @keyword)";
                 keyword = $"%{keyword}%";
-            } 
+            }
             filter = filter.StringTrimStart(" AND ");
 
             //排序
@@ -57,10 +57,89 @@ namespace molilian.api.Controllers
                .Page(size, page)
                .Order(orderBy)
                .PageList<dynamic>(getTotal);
-             
+
             return new APIResult(new { data = result });
         }
 
+
+
+        [HttpPost]
+        public async Task<ActionResult> update([FromBody] JsonElement form)
+        {
+            var clientIp = _accessor.HttpContext.GetUserIp();
+            var token = provider.Get(_accessor.HttpContext);
+
+            int id = form.Read<int>("id", 0);
+            string name = form.Read<string>("name", string.Empty);
+            string val = form.Read<string>("val", string.Empty);
+
+            if (id == 0)
+            {
+                return new APIResult(new { data = new { success = false, msg = "更新失败,请检查输入参数" } });
+            }
+
+            int result = 0;
+            switch (name)
+            {
+                case "status":
+                    bool bVal = val.Equals("True");
+                    result = new DBContext.Table("aliyun_pool")
+                           .Add(name, bVal)
+                           .Add("last_time", DateTime.Now)
+                           .Where("id=@id", new { id })
+                           .Update();
+                    break;
+                case "balance":
+                    var item = new DBContext.Table("aliyun_pool").Get<dynamic>("id=@id", new { id });
+                    if (string.IsNullOrEmpty(item.accessKeyId)) result = 0;
+                    decimal amout = 0;
+                    try
+                    {
+                        AliyunCore core = new AliyunCore(item.id);
+                        var response = core.QueryAccountBalance();
+                        var balance = response.Body.Data.AvailableAmount;
+                        if (decimal.TryParse(balance, out amout))
+                        {
+                            result = 1;
+                            AliyunPoolCore.UpdateDrawBalance(item.name, amout);
+                            if (item.balance != amout && amout <= item.balance_alert_threshold)
+                            {
+                                string message = $"【{item.company}】阿里云当前余额:{amout} 元";
+                                NotifyCore.AnPushNotify("余额预警", message);
+                                NotifyCore.Notify(new NifyMessage
+                                {
+                                    message = message,
+                                    priority = NifyMessagePriority.high,
+                                    tags = ["red_circle"]
+                                });
+                            }
+                        }
+                    }
+                    catch (Exception ex)
+                    {
+                        _ = new LoggerLibrary("aliyun", "balance_error")
+                          .Info($"Account:{item.id}\tbalance:{amout}")
+                          .Info(ex.Message, ex.StackTrace)
+                          .SaveAsync();
+                    }
+                    break;
+                default:
+                    return new APIResult(new { data = new { success = false, msg = "更新失败,未授权操作" } });
+            }
+
+
+            bool success = result > 0;
+            if (success)
+            {
+                OperationLogCore.LogOperation(token.AccessKey, clientIp, $"aliyun_pool:{id}:{name}", string.Empty, val);
+            }
+            return new APIResult(new
+            {
+                data = new { success, msg = success ? "更新成功" : "更新失败,请检查输入信息" },
+            });
+        }
+
+
         [HttpPost]
         public ActionResult ecs_list([FromBody] JsonElement form)
         {

+ 51 - 2
molilian.api/Controllers/public/ApiController.cs

@@ -12,6 +12,8 @@ using COSXML.Network;
 using System.Linq;
 using static dodohold.core.ZTOExpress.CreateOrderArgs;
 using TencentCloud.Lighthouse.V20200324.Models;
+using TencentCloud.Ame.V20190916.Models;
+using TencentCloud.Omics.V20221128.Models;
 
 namespace molilian.api.Controllers
 {
@@ -27,6 +29,51 @@ namespace molilian.api.Controllers
             core = new TaokeOpenCore();
         }
 
+        //[HttpGet]
+        //public async Task<ActionResult> RequestAsync([FromQuery] string url, [FromQuery] int proxyId)
+        //{
+        //    if (string.IsNullOrEmpty(url))
+        //    {
+        //        return BadRequest("URL cannot be empty");
+        //    }
+
+        //    var proxy = ProxyNodesCore.GetOne(proxyId);
+        //    if (proxy == null)
+        //    {
+        //        return Unauthorized("Invalid proxy configuration");
+        //    }
+        //    WebClientUtility cli = new()
+        //    {
+        //        Proxy = proxy
+        //    };
+        //    await cli.RequestAsync(url);
+        //    var content = cli.Body();
+        //    var contentType = cli.ResponseMessage.Content.Headers.ContentType?.MediaType ?? "text/plain";
+        //    return Content(content, contentType);
+        //}
+
+        [HttpGet]
+        public async Task<ActionResult> RequestAsync([FromQuery] string url, [FromQuery] string proxy)
+        {
+            if (string.IsNullOrEmpty(url))
+            {
+                return BadRequest("URL cannot be empty");
+            }
+
+            WebProxy _proxy = ProxyManager.Parse(proxy);
+            WebClientUtility cli = new();
+            cli.Proxy = _proxy;
+            cli.Timeout = TimeSpan.FromSeconds(10);
+            await cli.RequestAsync(url);
+            if (cli.Successed)
+            {
+                var content = cli.Body();
+
+                var contentType = cli.ResponseMessage.Content.Headers.ContentType?.MediaType ?? "text/plain";
+                return Content(content, contentType);
+            }
+            throw cli.ResponseException;
+        }
 
 
         [HttpPost]
@@ -38,6 +85,7 @@ namespace molilian.api.Controllers
             var oaid = form.Read("oaid", string.Empty);
             var scene = form.Read("scene", string.Empty);
             var recommand = form.Read("recommand", true);
+            var aid = form.Read("aid", 0);
 
             //验证签名
             if (string.IsNullOrEmpty(a) || string.IsNullOrEmpty(sign))
@@ -67,7 +115,7 @@ namespace molilian.api.Controllers
                 var bytes = new WebClientUtility().Request(url).ResponseBody;
                 img = Convert.ToBase64String(bytes);
             }
-            return await core.PromotionQueryAsync(img, oaid, ip, scene, recommand);
+            return await core.PromotionQueryAsync(img, oaid, ip, scene, recommand, false, aid);
         }
 
 
@@ -81,6 +129,7 @@ namespace molilian.api.Controllers
             var scene = form.Read("scene", string.Empty);
             var recommand = form.Read("recommand", true);
             var debug = form.Read("debug", false);
+            var aid = form.Read("aid", 0);
 
             if (!string.IsNullOrEmpty(url))
             {
@@ -94,7 +143,7 @@ namespace molilian.api.Controllers
                 oaid = $"{rand.Next(100000, 999999)}-{rand.Next(100000, 999999)}-{rand.Next(100000, 999999)}";
             }
 
-            return await core.PromotionQueryAsync(img, oaid, ip, scene, recommand, debug);
+            return await core.PromotionQueryAsync(img, oaid, ip, scene, recommand, debug, aid);
         }
 
 

+ 340 - 0
molilian.api/Controllers/public/FeatureController.cs

@@ -0,0 +1,340 @@
+using molilian.core;
+using dodohold.core;
+using Microsoft.AspNetCore.Mvc;
+using System.Text;
+using System.Text.Json;
+using System.Collections.Concurrent;
+using System.Diagnostics;
+namespace molilian.api.Controllers
+{
+
+    [ApiController]
+    [Route("[controller]/[action]")]
+    public class FeatureController : ControllerBase
+    {
+
+        protected IHttpContextAccessor _accessor;
+        public FeatureController(IHttpContextAccessor accessor)
+        {
+            _accessor = accessor;
+        }
+
+        [HttpGet]
+        public async Task<ActionResult> CSRedis(int thread, int durationSeconds = 30)
+        {
+            var watch = System.Diagnostics.Stopwatch.StartNew();
+            var cts = new CancellationTokenSource();
+            var performanceLogger = new RedisPerformanceLogger();
+
+            long totalRequests = 0;
+            long successCount = 0;
+            long failureCount = 0;
+
+            var metricsQueue = new ConcurrentQueue<RedisOperationMetrics>();
+
+            var tasks = new List<Task>();
+            for (int i = 0; i < thread; i++)
+            {
+                tasks.Add(Task.Run(() =>
+                {
+                    while (!cts.Token.IsCancellationRequested)
+                    {
+                        var metrics = new RedisOperationMetrics();
+                        try
+                        {
+                            // 写入操作
+                            var sw = Stopwatch.StartNew();
+                            var testValue = "test value";
+                            var key = $"test:csredis:{Guid.NewGuid()}";
+                            RedisHelper.Set(key, testValue, 60);
+                            sw.Stop();
+                            metrics.WriteTimeMs = sw.ElapsedMilliseconds;
+                            metrics.KeySize = Encoding.UTF8.GetByteCount(key);
+                            metrics.ValueSize = Encoding.UTF8.GetByteCount(testValue);
+
+                            // IncrBy操作
+                            sw.Restart();
+                            RedisHelper.IncrBy("counter:csredis", 1);
+                            sw.Stop();
+                            metrics.IncrByTimeMs = sw.ElapsedMilliseconds;
+
+                            // 读取操作
+                            sw.Restart();
+                            var value = RedisHelper.Get("counter:csredis");
+                            sw.Stop();
+                            metrics.ReadTimeMs = sw.ElapsedMilliseconds;
+
+                            metrics.IsSuccess = true;
+                            Interlocked.Increment(ref successCount);
+                        }
+                        catch (Exception ex)
+                        {
+                            metrics.IsSuccess = false;
+                            metrics.ErrorMessage = ex.Message;
+                            Interlocked.Increment(ref failureCount);
+
+                            string message = $"{ex.Message}\n{ex.StackTrace}";
+                            NotifyCore.Notify(new NifyMessage
+                            {
+                                message = message,
+                                priority = NifyMessagePriority.high,
+                                tags = ["red_circle"]
+                            });
+                            new LoggerLibrary("Feature").Info(message).SaveAsync();
+                        }
+                        finally
+                        {
+                            metricsQueue.Enqueue(metrics);
+                            Interlocked.Increment(ref totalRequests);
+                        }
+                    }
+                }, cts.Token));
+            }
+
+            await Task.Delay(TimeSpan.FromSeconds(durationSeconds));
+            cts.Cancel();
+
+            try
+            {
+                await Task.WhenAll(tasks);
+            }
+            catch (OperationCanceledException)
+            {
+                // 预期的取消异常
+            }
+
+            watch.Stop();
+            var elapsedMs = watch.ElapsedMilliseconds;
+            var qps = totalRequests * 1000.0 / elapsedMs;
+
+            var metrics = metricsQueue.ToList();
+            var writeStats = RedisOperationMetrics.CalculateStatistics(metrics, m => m.WriteTimeMs);
+            var incrByStats = RedisOperationMetrics.CalculateStatistics(metrics, m => m.IncrByTimeMs);
+            var readStats = RedisOperationMetrics.CalculateStatistics(metrics, m => m.ReadTimeMs);
+
+            var resultData = new Dictionary<string, object>
+            {
+                ["ConcurrentThreads"] = thread,
+                ["DurationSeconds"] = durationSeconds,
+                ["TotalTimeMs"] = elapsedMs,
+                ["TotalRequests"] = totalRequests,
+                ["SuccessCount"] = successCount,
+                ["FailureCount"] = failureCount,
+                ["QPS"] = Math.Round(qps, 2),
+                ["SuccessRate"] = Math.Round((double)successCount / totalRequests * 100, 2),
+                ["RedisMetrics"] = new
+                {
+                    Write = writeStats,
+                    IncrBy = incrByStats,
+                    Read = readStats
+                }
+            };
+
+            await performanceLogger.LogPerformanceResult("CSRedis", resultData);
+
+            return new APIResult(resultData);
+        }
+
+        [HttpGet]
+        public async Task<ActionResult> FreeRedis(int thread, int durationSeconds = 30)
+        {
+            var watch = System.Diagnostics.Stopwatch.StartNew();
+            var cts = new CancellationTokenSource();
+            var performanceLogger = new RedisPerformanceLogger();
+
+            long totalRequests = 0;
+            long successCount = 0;
+            long failureCount = 0;
+
+            var metricsQueue = new ConcurrentQueue<RedisOperationMetrics>();
+            var redis = YunhuiKit.RedisKit.Instance;
+
+            var tasks = new List<Task>();
+            for (int i = 0; i < thread; i++)
+            {
+                tasks.Add(Task.Run(() =>
+                {
+                    while (!cts.Token.IsCancellationRequested)
+                    {
+                        var metrics = new RedisOperationMetrics();
+                        try
+                        {
+                            // 写入操作
+                            var sw = Stopwatch.StartNew();
+                            var testValue = "test value";
+                            var key = $"test:freeredis:{Guid.NewGuid()}";
+                            redis.Set(key, testValue, 60);
+                            sw.Stop();
+                            metrics.WriteTimeMs = sw.ElapsedMilliseconds;
+                            metrics.KeySize = Encoding.UTF8.GetByteCount(key);
+                            metrics.ValueSize = Encoding.UTF8.GetByteCount(testValue);
+
+                            // IncrBy操作
+                            sw.Restart();
+                            redis.IncrBy("counter:freeredis", 1);
+                            sw.Stop();
+                            metrics.IncrByTimeMs = sw.ElapsedMilliseconds;
+
+                            // 读取操作
+                            sw.Restart();
+                            var value = redis.Get("counter:freeredis");
+                            sw.Stop();
+                            metrics.ReadTimeMs = sw.ElapsedMilliseconds;
+
+                            metrics.IsSuccess = true;
+                            Interlocked.Increment(ref successCount);
+                        }
+                        catch (Exception ex)
+                        {
+                            metrics.IsSuccess = false;
+                            metrics.ErrorMessage = ex.Message;
+                            Interlocked.Increment(ref failureCount);
+
+                            string message = $"{ex.Message}\n{ex.StackTrace}";
+                            NotifyCore.Notify(new NifyMessage
+                            {
+                                message = message,
+                                priority = NifyMessagePriority.high,
+                                tags = ["red_circle"]
+                            });
+                            new LoggerLibrary("Feature").Info(message).SaveAsync();
+                        }
+                        finally
+                        {
+                            metricsQueue.Enqueue(metrics);
+                            Interlocked.Increment(ref totalRequests);
+                        }
+                    }
+                }, cts.Token));
+            }
+
+            await Task.Delay(TimeSpan.FromSeconds(durationSeconds));
+            cts.Cancel();
+
+            try
+            {
+                await Task.WhenAll(tasks);
+            }
+            catch (OperationCanceledException)
+            {
+                // 预期的取消异常
+            }
+
+            watch.Stop();
+            var elapsedMs = watch.ElapsedMilliseconds;
+            var qps = totalRequests * 1000.0 / elapsedMs;
+
+            var metrics = metricsQueue.ToList();
+            var writeStats = RedisOperationMetrics.CalculateStatistics(metrics, m => m.WriteTimeMs);
+            var incrByStats = RedisOperationMetrics.CalculateStatistics(metrics, m => m.IncrByTimeMs);
+            var readStats = RedisOperationMetrics.CalculateStatistics(metrics, m => m.ReadTimeMs);
+
+            var resultData = new Dictionary<string, object>
+            {
+                ["ConcurrentThreads"] = thread,
+                ["DurationSeconds"] = durationSeconds,
+                ["TotalTimeMs"] = elapsedMs,
+                ["TotalRequests"] = totalRequests,
+                ["SuccessCount"] = successCount,
+                ["FailureCount"] = failureCount,
+                ["QPS"] = Math.Round(qps, 2),
+                ["SuccessRate"] = Math.Round((double)successCount / totalRequests * 100, 2),
+                ["RedisMetrics"] = new
+                {
+                    Write = writeStats,
+                    IncrBy = incrByStats,
+                    Read = readStats
+                }
+            };
+
+            await performanceLogger.LogPerformanceResult("FreeRedis", resultData);
+
+            return new APIResult(resultData);
+
+        }
+    }
+
+
+    public class RedisPerformanceLogger
+    {
+        private readonly LoggerLibrary _logger;
+        private const string LoggerName = "RedisPerformance";
+
+        public RedisPerformanceLogger()
+        {
+            _logger = new LoggerLibrary(LoggerName);
+        }
+
+        public async Task LogPerformanceResult(string clientType, Dictionary<string, object> metrics)
+        {
+            var logMessage = new StringBuilder();
+            logMessage.AppendLine($"Redis Performance Test Result - {clientType}");
+            logMessage.AppendLine($"DateTime: {DateTime.Now:yyyy-MM-dd HH:mm:ss}");
+
+            foreach (var kvp in metrics)
+            {
+                logMessage.AppendLine($"{kvp.Key}: {JsonSerializer.Serialize(kvp.Value, new JsonSerializerOptions
+                {
+                    WriteIndented = true
+                })}");
+            }
+
+            await _logger.Info(logMessage.ToString()).SaveAsync();
+        }
+    }
+
+
+    public class RedisOperationMetrics
+    {
+        public long WriteTimeMs { get; set; }
+        public long IncrByTimeMs { get; set; }
+        public long ReadTimeMs { get; set; }
+        public DateTime OperationTime { get; set; } = DateTime.Now;
+        public string OperationType { get; set; }
+        public bool IsSuccess { get; set; }
+        public string ErrorMessage { get; set; }
+        public int RetryCount { get; set; }
+        public long KeySize { get; set; }
+        public long ValueSize { get; set; }
+
+        public static double CalculatePercentile(List<long> times, double percentile)
+        {
+            if (times == null || times.Count == 0) return 0;
+
+            var sortedTimes = times.OrderBy(t => t).ToList();
+            var index = (int)Math.Ceiling(percentile / 100.0 * sortedTimes.Count) - 1;
+            return sortedTimes[Math.Max(0, index)];
+        }
+
+        public static OperationStatistics CalculateStatistics(IEnumerable<RedisOperationMetrics> metrics, Func<RedisOperationMetrics, long> timeSelector)
+        {
+            var times = metrics.Select(timeSelector).ToList();
+
+            return new OperationStatistics
+            {
+                Average = times.Any() ? Math.Round(times.Average(), 2) : 0,
+                Median = CalculatePercentile(times, 50),
+                P95 = CalculatePercentile(times, 95),
+                P99 = CalculatePercentile(times, 99),
+                Max = times.Any() ? times.Max() : 0,
+                Min = times.Any() ? times.Min() : 0,
+                Count = times.Count,
+                TotalTime = times.Sum()
+            };
+        }
+    }
+
+    public class OperationStatistics
+    {
+        public double Average { get; set; }
+        public double Median { get; set; }
+        public double P95 { get; set; }
+        public double P99 { get; set; }
+        public long Max { get; set; }
+        public long Min { get; set; }
+        public int Count { get; set; }
+        public long TotalTime { get; set; }
+    }
+
+
+}

+ 5 - 15
molilian.api/Controllers/public/TaskController.cs

@@ -573,13 +573,8 @@ namespace molilian.api.Controllers
                                 account.status = false;
                                 JdPoolCore.Disabled(account.id, account.name, ex.Message);
                             }
-                            message = $"【JD报表接口异常】{account.id}:{account.name}\tqueryTodaySpreadEffectData\n{account.Convert2Json()}\n{ex.Message}\n{ex.StackTrace}";
-                            NotifyCore.Notify(new NifyMessage
-                            {
-                                message = message,
-                                priority = NifyMessagePriority.high,
-                                tags = ["red_circle"]
-                            });
+                            message = $"【JD报表接口异常】{account.id}:{account.name}\tqueryTodaySpreadEffectData\n{ex.Message}\n{ex.StackTrace}";
+                            NotifyCore.Notify(message);
                             continue;
                         }
                     }
@@ -734,12 +729,7 @@ namespace molilian.api.Controllers
                                 JdPoolCore.Disabled(account.id, account.name, ex.Message);
                             }
                             message = $"【JD报表接口异常】{account.id}:{account.name}\tquerySpreadEffectData\n{ex.Message}\n{ex.StackTrace}";
-                            NotifyCore.Notify(new NifyMessage
-                            {
-                                message = message,
-                                priority = NifyMessagePriority.high,
-                                tags = ["red_circle"]
-                            });
+                            NotifyCore.Notify(message);
                             continue;
                         }
                     }
@@ -928,8 +918,8 @@ namespace molilian.api.Controllers
                     message = "无效URL",
                 });
             }
-
-            (success, string content) = await alimama.GetDesiredUrlAsync(url);
+            WebProxy proxy = ProxyNodesCore.RandomOne(account.nodeName);
+            (success, string content) = await alimama.GetDesiredUrlAsync(proxy, url);
             if (content.Contains("霸下通用 web 页面-验证码"))
             {
                 message = "霸下验证码";

+ 16 - 6
molilian.api/Dockerfile

@@ -1,36 +1,46 @@
-#See https://aka.ms/customizecontainer to learn how to customize your debug container and how Visual Studio uses this Dockerfile to build your images for faster debugging.
+# 隸キ蜿る� https://aka.ms/customizecontainer 莉・莠�ァ」螯ゆス戊�螳壻ケ芽ー�ッ募ョケ蝎ィ�御サ・蜿� Visual Studio 螯ゆス穂スソ逕ィ豁、 Dockerfile 逕滓�譏�蜒丈サ・譖エ蠢ォ蝨ー霑幄。瑚ー�ッ輔€�
 
+# 豁、髦カ谿オ逕ィ莠主惠蠢ォ騾滓ィ。蠑�(鮟倩ョ、荳コ隹�ッ暮�鄂ョ)荳倶サ� VS 霑占。梧慮
 FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
+#USER $APP_UID
 USER root
+
 WORKDIR /app
 EXPOSE 8080
 EXPOSE 8081
 
+
+# 豁、髦カ谿オ逕ィ莠守函謌先恪蜉。鬘ケ逶ョ
 FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
 ARG BUILD_CONFIGURATION=Release
 WORKDIR /src
+COPY ["nuget.config", "."]
 COPY ["molilian.api/molilian.api.csproj", "molilian.api/"]
-RUN dotnet restore "./molilian.api/./molilian.api.csproj"
+COPY ["molilian.core/molilian.core.csproj", "molilian.core/"]
+COPY ["taobao-sdk-netcore-auto_1719572210878-20240628-source/topsdk-netcore.csproj", "taobao-sdk-netcore-auto_1719572210878-20240628-source/"]
+RUN dotnet restore "./molilian.api/molilian.api.csproj"
+#RUN dotnet restore "./molilian.api/./molilian.api.csproj" --configfile "./nuget.config"
 COPY . .
 WORKDIR "/src/molilian.api"
 RUN dotnet build "./molilian.api.csproj" -c $BUILD_CONFIGURATION -o /app/build
 
+# 豁、髦カ谿オ逕ィ莠主書蟶�ヲ∝、榊宛蛻ー譛€扈磯亳谿オ逧�恪蜉。鬘ケ逶ョ
 FROM build AS publish
 ARG BUILD_CONFIGURATION=Release
 RUN dotnet publish "./molilian.api.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false
 
+# 豁、髦カ谿オ蝨ィ逕滉コァ荳ュ菴ソ逕ィ�梧�蝨ィ蟶ク隗�ィ。蠑丈ク倶サ� VS 霑占。梧慮菴ソ逕ィ(蝨ィ荳堺スソ逕ィ隹�ッ暮�鄂ョ譌カ荳コ鮟倩ョ、蛟シ)
 FROM base AS final
 WORKDIR /app
 COPY --from=publish /app/publish .
 
-
-# ノ靹テヌ��靹テコヘラヨキ﨣狡�
+# 隶セ鄂ョ蛹コ蝓溯ョセ鄂ョ蜥悟ュ礼ャヲ郛也��
 ENV LANG en_US.UTF-8
 ENV LANGUAGE en_US:en
 ENV LC_ALL en_US.UTF-8
 
-# ノ靹テハアヌ�
+# 隶セ鄂ョ譌カ蛹コ
 RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
 RUN echo "Asia/Shanghai" > /etc/timezone
 
-ENTRYPOINT ["dotnet", "molilian.api.dll"]
+ENTRYPOINT ["dotnet", "molilian.api.dll"]

+ 40 - 0
molilian.api/Dockerfile.original

@@ -0,0 +1,40 @@
+#See https://aka.ms/customizecontainer to learn how to customize your debug container and how Visual Studio uses this Dockerfile to build your images for faster debugging.
+
+FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
+USER root
+WORKDIR /app
+EXPOSE 8080
+EXPOSE 8081
+
+FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
+ARG BUILD_CONFIGURATION=Release
+WORKDIR /src
+
+COPY ["nuget.config", "."]
+COPY ["molilian.api/molilian.api.csproj", "molilian.api/"]
+RUN dotnet restore "./molilian.api/./molilian.api.csproj" --configfile "./nuget.config"
+
+
+COPY . .
+WORKDIR "/src/molilian.api"
+RUN dotnet build "./molilian.api.csproj" -c $BUILD_CONFIGURATION -o /app/build
+
+FROM build AS publish
+ARG BUILD_CONFIGURATION=Release
+RUN dotnet publish "./molilian.api.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false
+
+FROM base AS final
+WORKDIR /app
+COPY --from=publish /app/publish .
+
+
+# 设置区域设置和字符编码
+ENV LANG en_US.UTF-8
+ENV LANGUAGE en_US:en
+ENV LC_ALL en_US.UTF-8
+
+# 设置时区
+RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
+RUN echo "Asia/Shanghai" > /etc/timezone
+
+ENTRYPOINT ["dotnet", "molilian.api.dll"]

+ 0 - 11
molilian.api/Properties/PublishProfiles/ccr.ccs.tencentyun.com_shaobin.pubxml.user

@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-https://go.microsoft.com/fwlink/?LinkID=208121.
--->
-<Project>
-  <PropertyGroup>
-    <TimeStampOfAssociatedLegacyPublishXmlFile />
-    <History>False|2024-05-20T18:19:59.7003730Z;True|2024-05-21T01:38:06.0801891+08:00;False|2024-05-21T01:28:54.6915861+08:00;False|2024-05-21T01:21:24.1793095+08:00;True|2024-05-20T23:43:12.1284798+08:00;True|2024-05-20T17:17:02.1614770+08:00;True|2024-05-19T01:26:14.4937967+08:00;True|2024-05-18T23:43:43.1846184+08:00;True|2024-05-18T20:53:23.6522806+08:00;True|2024-05-03T22:57:48.7588014+08:00;True|2024-05-03T22:33:25.9876078+08:00;True|2024-05-03T22:25:11.9112284+08:00;False|2024-05-03T22:06:26.3115169+08:00;False|2024-05-03T22:01:42.1789367+08:00;False|2024-05-03T21:43:54.4666424+08:00;True|2024-04-29T20:30:49.5264428+08:00;True|2024-04-29T13:41:40.9181854+08:00;True|2024-04-29T13:36:42.3962074+08:00;False|2024-04-29T13:35:23.0198470+08:00;False|2024-04-29T13:23:33.1908897+08:00;False|2024-04-29T13:22:44.7107078+08:00;False|2024-04-29T13:20:21.6003940+08:00;True|2024-04-29T01:08:38.3907121+08:00;False|2024-04-29T01:02:34.7297243+08:00;False|2024-04-29T00:59:20.3808933+08:00;False|2024-04-29T00:57:58.6936336+08:00;False|2024-04-29T00:00:43.9313694+08:00;False|2024-04-28T23:59:52.4054736+08:00;False|2024-04-28T23:58:41.2396317+08:00;True|2024-04-25T22:05:48.6258880+08:00;True|2024-04-25T22:04:18.9044673+08:00;True|2024-04-25T02:11:47.7147921+08:00;True|2024-04-25T01:37:51.4669453+08:00;True|2024-04-23T21:57:15.0394478+08:00;True|2024-04-23T16:42:55.6922746+08:00;True|2024-04-23T15:27:10.3404869+08:00;True|2024-04-23T15:23:49.7671268+08:00;True|2024-04-23T15:21:27.9969435+08:00;True|2024-04-23T15:16:37.6731585+08:00;False|2024-04-23T15:00:12.7372536+08:00;True|2024-04-23T14:33:52.7541898+08:00;True|2024-04-23T14:31:07.4221289+08:00;True|2024-04-23T14:26:21.6139157+08:00;True|2024-04-22T16:11:01.0290108+08:00;True|2024-04-22T15:10:34.9050235+08:00;</History>
-    <LastFailureDetails />
-  </PropertyGroup>
-</Project>

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 7
molilian.api/Properties/PublishProfiles/https___ccr.ccs.tencentyun.com_shaobin.pubxml.user


+ 0 - 0
molilian.api/Properties/PublishProfiles/ccr.ccs.tencentyun.com_shaobin.pubxml → molilian.api/Properties/PublishProfiles/latest.pubxml


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 7 - 0
molilian.api/Properties/PublishProfiles/latest.pubxml.user


+ 1 - 2
molilian.api/Properties/PublishProfiles/https___ccr.ccs.tencentyun.com_shaobin.pubxml → molilian.api/Properties/PublishProfiles/tester.pubxml

@@ -7,8 +7,7 @@ https://go.microsoft.com/fwlink/?LinkID=208121.
     <WebPublishMethod>Custom</WebPublishMethod>
     <DockerPublish>true</DockerPublish>
     <RegistryUrl>https://ccr.ccs.tencentyun.com/shaobin</RegistryUrl>
-    <UserName />
-    <PublishImageTag>latest</PublishImageTag>
+    <PublishImageTag>tester</PublishImageTag>
     <PublishProvider>ContainerRegistry</PublishProvider>
     <LastUsedBuildConfiguration>Release</LastUsedBuildConfiguration>
     <LastUsedPlatform>Any CPU</LastUsedPlatform>

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 7 - 0
molilian.api/Properties/PublishProfiles/tester.pubxml.user


+ 1 - 1
molilian.api/Properties/launchSettings.json

@@ -6,7 +6,7 @@
       "launchUrl": "swagger",
       "environmentVariables": {
         "ASPNETCORE_ENVIRONMENT": "Development",
-        "EndPoint": "admin",
+        "EndPoint": "bj",
         "NtfyServer": "https://ntfy.yunhui800.com/5Sq9BytXXM5WDY3G",
         "ANPush": "",
         "DBType": "MySQL",

+ 1 - 0
molilian.api/molilian.api.csproj

@@ -14,6 +14,7 @@
     <PackageReference Include="dodohold.core" Version="1.0.1.14" />
     <PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.20.0-Preview.1" />
     <PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
+    <PackageReference Include="YunhuiKit" Version="0.0.3" />
   </ItemGroup>
 
   <ItemGroup>

+ 1 - 1
molilian.api/molilian.api.csproj.user

@@ -2,7 +2,7 @@
 <Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <PropertyGroup>
     <ActiveDebugProfile>http</ActiveDebugProfile>
-    <NameOfLastUsedPublishProfile>E:\project\2024\molilian\server\molilian.api\Properties\PublishProfiles\https___ccr.ccs.tencentyun.com_shaobin.pubxml</NameOfLastUsedPublishProfile>
+    <NameOfLastUsedPublishProfile>E:\project\2024\molilian\server\molilian.api\Properties\PublishProfiles\latest.pubxml</NameOfLastUsedPublishProfile>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
     <DebuggerFlavor>ProjectDebugger</DebuggerFlavor>

+ 8 - 0
molilian.core/Core/NotifyCore.cs

@@ -25,6 +25,14 @@ namespace molilian.core
             }
         }
 
+        public static void Notify(string message)
+        {
+            if (!string.IsNullOrEmpty(_base_url))
+            {
+                NifyPlus.Send(_base_url, new NifyMessage { message = message });
+            }
+        }
+
         public static void Notify(NifyMessage message)
         {
             if (!string.IsNullOrEmpty(_base_url))

+ 55 - 1
molilian.core/Core/ProxyNodesCore.cs

@@ -11,6 +11,7 @@ using System.Xml.Linq;
 using System.Net;
 using TencentCloud.Mrs.V20200910.Models;
 using static molilian.core.TkPoolCore;
+using TencentCloud.Ecm.V20190719.Models;
 
 
 namespace molilian.core
@@ -33,7 +34,49 @@ namespace molilian.core
             var list = List();
             if (!list.Any()) return null;
 
-            var ProxyNodesDTO = list.Where(e => SelectEndPointUseProxy(e, node)).OrderBy(l => Guid.NewGuid()).FirstOrDefault();
+            // 处理包含逗号的节点参数
+            string selectedNode = node;
+            if (node.Contains(","))
+            {
+                var nodes = node.Split(',', StringSplitOptions.RemoveEmptyEntries)
+                               .Select(n => n.Trim())
+                               .Where(n => !string.IsNullOrEmpty(n))
+                               .ToArray();
+
+                if (nodes.Length > 0)
+                {
+                    // 随机选择一个节点
+                    var random = new Random();
+                    selectedNode = nodes[random.Next(nodes.Length)];
+                }
+            }
+
+
+            var ProxyNodesDTO = list.Where(e => SelectEndPointUseProxy(e, selectedNode))
+                                   .OrderBy(l => Guid.NewGuid())
+                                   .FirstOrDefault();
+            if (ProxyNodesDTO == null) return null;
+
+#if DEBUG
+            return new WebProxy
+            {
+                Address = new Uri("http://bjapi.molilian.com:20010"),
+                Credentials = new NetworkCredential("molilian", "Bhquvmkn8zLO36lGjuqk")
+            };
+#endif
+
+            return new WebProxy
+            {
+                Address = new Uri(ProxyNodesDTO.server),
+                Credentials = new NetworkCredential(ProxyNodesDTO.username, ProxyNodesDTO.password)
+            };
+        }
+        public static WebProxy? GetOne(int nodeid)
+        {
+            var list = List();
+            if (!list.Any()) return null;
+
+            var ProxyNodesDTO = list.Where(e => SelectEndPointUseProxy(e, nodeid)).OrderBy(l => Guid.NewGuid()).FirstOrDefault();
             if (ProxyNodesDTO == null) return null;
 
             return new WebProxy
@@ -42,6 +85,8 @@ namespace molilian.core
                 Credentials = new NetworkCredential(ProxyNodesDTO.username, ProxyNodesDTO.password)
             };
         }
+
+
         private static bool SelectEndPointUseProxy(ProxyNodesDTO item, string node = "")
         {
             if (!string.IsNullOrEmpty(_end_point) && !string.IsNullOrEmpty(item.end_point))
@@ -50,6 +95,15 @@ namespace molilian.core
             }
             return string.IsNullOrEmpty(node) || item.name == node;
         }
+        private static bool SelectEndPointUseProxy(ProxyNodesDTO item, int nodeid)
+        {
+            if (!string.IsNullOrEmpty(_end_point) && !string.IsNullOrEmpty(item.end_point))
+            {
+                if (item.end_point != _end_point) return false;
+            }
+            return nodeid > 0 || item.id == nodeid;
+        }
+
         public static WebProxy? RandomOne(string excludeNode = "")
         {
 

+ 12 - 1
molilian.core/Core/aliyun/AliyunPoolCore.cs

@@ -72,16 +72,27 @@ namespace molilian.core
             foreach (var item in list)
             {
                 if (string.IsNullOrEmpty(item.accessKeyId)) continue;
+
                 decimal amout = 0;
                 try
                 {
-
                     AliyunCore core = new AliyunCore(item.id);
                     var response = core.QueryAccountBalance();
                     var balance = response.Body.Data.AvailableAmount;
                     if (decimal.TryParse(balance, out amout))
                     {
                         UpdateDrawBalance(item.name, amout);
+                        if (item.balance != amout && amout <= item.balance_alert_threshold)
+                        {
+                            string message = $"【{item.company}】阿里云当前余额:{amout} 元";
+                            NotifyCore.AnPushNotify("余额预警", message);
+                            NotifyCore.Notify(new NifyMessage
+                            {
+                                message = message,
+                                priority = NifyMessagePriority.high,
+                                tags = ["red_circle"]
+                            });
+                        }
                     }
                 }
                 catch (Exception ex)

+ 2 - 2
molilian.core/Core/cps/ElePoolCore.cs

@@ -92,11 +92,11 @@ namespace molilian.core
             RedisHelper.Expire(cache_key, 3600);
             NotifyCore.Notify(new NifyMessage
             {
-                message = $"【京东联盟】没有匹配账号",
+                message = $"【饿了么联盟】没有匹配账号",
                 priority = NifyMessagePriority.high,
                 tags = ["red_circle"]
             });
-            NotifyCore.AnPushNotify("没账号", $"【京东联盟】没有匹配账号");
+            NotifyCore.AnPushNotify("没账号", $"【饿了么联盟】没有匹配账号");
         }
 
     }

+ 2 - 2
molilian.core/Core/cps/MeituanPoolCore.cs

@@ -88,11 +88,11 @@ namespace molilian.core
             RedisHelper.Expire(cache_key, 3600);
             NotifyCore.Notify(new NifyMessage
             {
-                message = $"【京东联盟】没有匹配账号",
+                message = $"【美团联盟】没有匹配账号",
                 priority = NifyMessagePriority.high,
                 tags = ["red_circle"]
             });
-            NotifyCore.AnPushNotify("没账号", $"【京东联盟】没有匹配账号");
+            NotifyCore.AnPushNotify("没账号", $"【美团联盟】没有匹配账号");
         }
 
     }

+ 1 - 0
molilian.core/Core/log/cps.cs

@@ -60,6 +60,7 @@ namespace molilian.core
                 .Add("channel", data.channel)
                 .Add("accountId", data.accountId)
                 .Add("accountName", data.accountName)
+                .Add("proxy_node", data.proxy_node)
                 .Add("rawContent", data.rawContent)
                 .Add("rawContent2", data.rawContent2)
                 .Add("success", data.success)

+ 1 - 0
molilian.core/Core/log/dy.cs

@@ -28,6 +28,7 @@ namespace molilian.core
                         .Add("channel", (int)data.channel)
                         .Add("accountId", data.accountId)
                         .Add("accountName", data.accountName)
+                        .Add("proxy_node", data.proxy_node)
                         .Add("rawContent", data.rawContent)
                         .Add("success", data.success)
                         .Add("message", data.message)

+ 1 - 0
molilian.core/Core/log/jd.cs

@@ -125,6 +125,7 @@ namespace molilian.core
                 .Add("channel", (int)data.channel)
                 .Add("accountId", data.accountId)
                 .Add("accountName", data.accountName)
+                .Add("proxy_node", data.proxy_node)
                 .Add("rawContent", data.rawContent)
                 .Add("success", data.success)
                 .Add("message", data.message)

+ 1 - 0
molilian.core/Core/log/ks.cs

@@ -109,6 +109,7 @@ namespace molilian.core
                 .Add("channel", (int)data.channel)
                 .Add("accountId", data.accountId)
                 .Add("accountName", data.accountName)
+                .Add("proxy_node", data.proxy_node)
                 .Add("rawContent", data.rawContent)
                 .Add("success", data.success)
                 .Add("message", data.message)

+ 1 - 0
molilian.core/Core/log/pdd.cs

@@ -114,6 +114,7 @@ namespace molilian.core
                 .Add("channel", (int)data.channel)
                 .Add("accountId", data.accountId)
                 .Add("accountName", data.accountName)
+                .Add("proxy_node", data.proxy_node)
                 .Add("rawContent", data.rawContent)
                 .Add("rawContent2", data.rawContent2)
                 .Add("success", data.success)

+ 1 - 0
molilian.core/Core/log/promotion.cs

@@ -58,6 +58,7 @@ namespace molilian.core
                 return new DBContext.Table(connection, tablename)
                     .Add("accountId", data.accountId)
                     .Add("accountName", data.accountName)
+                    .Add("proxy_node", data.proxy_node)
                     .Add("img", data.img)
                     .Add("ip", data.ip)
                     .Add("oaid", data.oaid)

+ 1 - 0
molilian.core/Core/log/taobao.cs

@@ -147,6 +147,7 @@ namespace molilian.core
                 .Add("linkType", (int)data.link_type)
                 .Add("accountId", data.accountId)
                 .Add("accountName", data.accountName)
+                .Add("proxy_node", data.proxy_node)
                 .Add("rawContent", data.rawContent)
                 .Add("success", data.success)
                 .Add("message", data.message)

+ 13 - 5
molilian.core/Core/taoke/TaokeOpenCore.cs

@@ -23,7 +23,7 @@ namespace molilian.core
         }
 
 
-        public async Task<APIResult> PromotionQueryAsync(string img, string oaid = "", string ip = "", string scene = "", bool recommand = true, bool debug = false)
+        public async Task<APIResult> PromotionQueryAsync(string img, string oaid = "", string ip = "", string scene = "", bool recommand = true, bool debug = false, int aid = 0)
         {
             PromotionQueryDTO result = new()
             {
@@ -68,7 +68,15 @@ namespace molilian.core
             }
             try
             {
-                var account = TkPoolCore.GetOne(TkPoolCore.TkAction.promotionQuery);
+                TkPoolDTO account;
+                if (aid == 0)
+                {
+                    account = TkPoolCore.GetOne(TkPoolCore.TkAction.promotionQuery);
+                }
+                else
+                {
+                    account = TkPoolCore.GetOne(aid);
+                }
                 if (account == null)
                 {
                     result.success = false;
@@ -86,11 +94,11 @@ namespace molilian.core
                     });
                 }
 
-
-                TaobaoOpenPlus taobao = new(account.appkey, account.appSecret, account.open_pid, debug);
+                var proxy = ProxyNodesCore.GetOne(account.nodeName);
+                TaobaoOpenPlus taobao = new(account.appkey, account.appSecret, account.open_pid, debug, proxy);
                 int timeout = _config.similar_timeout;
 #if DEBUG
-                timeout = 5000;
+                timeout = 50000;
 #endif
                 using var cts = new CancellationTokenSource();
                 cts.CancelAfter(timeout);

+ 28 - 26
molilian.core/Core/taoke/UnionParseCore.cs

@@ -246,19 +246,20 @@ namespace molilian.core
                     _ = TkLogCore.ParseLogAsync(result);
 
 
-                    //20241204 特例
-                    //if ("bj".Equals(EndPointCore.CurrentEndPoint))
-                    //{
-                    //    string ruleKey = $"tmp_rules2:tb:{DateTime.Now:yyyyMMdd}";
-                    //    var count = RedisHelper.Get<int>(ruleKey);
-                    //    if (DateTime.Now < DateTime.Parse("2024-12-09") && count < 500)
-                    //    {
-                    //        //result.deeplink_url = "tbopen://m.taobao.com/tbopen/index.html?action=ali.open.nav&module=h5&source=alimama&bc_fl_src=tunion_vipmedia_sy&h5Url=https%3A%2F%2Fs.click.taobao.com%2Ft%3Funion_lens%3DlensId%253APUB%25401733285378%25402105593d_0f2e_1938fdbfb08_56d2%254001%2540eyJmbG9vcklkIjozODg1Miiwiic3BtQiiI6Il9wb3J0YWxfdjJfcGFnZXNfYWN0aXZpdHlfb2ZmaWNpYWxfaW5kZXhfaHRtIn0ie%253BeventPageId%253A20150318020019405%26e%3Dm%253D2%2526s%253DHT55zNJ42uRw4vFB6t2Z2iperVdZeJviAMbqNcPEYg76sTlfBitgxDLxqsKAeUFqgEGu%252B0FGP7cWpIFXOotQwxwkghS%252B3Tth35QMLhvYd5WzAlsM3q9KBQgChlAI37hjOkwAUKujKr8%252BB0zf4OD7u5LL0QPsyT77slidLc%252FfR2bfW12dRBt0XJ7LmQijlljrM7kxpdONUAKgtf8I59Gmj7WOELdnGdZV3eHn14rW1PBcfk1oQPCr5xDqzYVRkKA1NNRdkxXQuw4cJIIUvt07Yd%252BUDC4b2HeVswJbDN6vSgUIAoZQCN%252B4Y859REbZnVo89hl0nxWy%252BeTjkOUQ%252FOHRwAPUBlppf%252Btjs7UNLsd2bI5z8saC7t5FlO9Zh8BraVZYIcqHs8UcdUpXL0nm%252FTxRaQ4VydfXBQxnSpQpV4IkRoOOqZbKHGSDxYLRK9woGjcZwM7sKH2NkQIJ%252Fov1pArqR5rCLGafPO1NzTpSwSQKdJD1UZJeBohmpzCclrzRGqIlouD5cf%252BfoU5VXRkZOvK%252FVyaa21c5k%252BY9DYGmadGiXn0jUIaYy7GzzyoG4bBR4UOYsQQxcVtq4KEjiVO%252FBgG2pWuj0Yecd3Dfdij0RQXJBsf3Oqj9M98VWj7lCjCC8ck8";
-                    //        result.deeplink_url = "tbopen://m.taobao.com/tbopen/index.html?source=auto&action=ali.open.nav&module=h5&bootImage=0&afc_route=1&bc_fl_src=growth_dhh_2200803434968_100-1930985-1595034112&dpa_Inid=159503411212096&dpa_material_id=530637422585&dpa_material_type=1&dpa_source_code=12096&force_no_smb=true&h5Url=https%3A%2F%2Fs.m.taobao.com%2Fh5%3Ffrom%3Dcustoms%26g_channelSrp%3Ddhhdpa_1232552832%26dpa_material_type%3D1%26ut_sk%3Dsearch%26spm%3Da2141.mb819t211c7%26sLaunch%3D0%26sKeep%3D1%26sModuleName%3Dsearch%26spm_back_up%3Da2141.mb819t211c7%26bc_fl_src%3Dgrowth_dhh_2200803434968_100-1930985-1595034112%26dpa_Inid%3D159503411212096%26dpa_material_id%3D530637422585%26dpa_material_type%3D1%26dpa_source_code%3D12096%26force_no_smb%3Dtrue%26itemIds%3D530637422585%26slk_actid%3D100000000207%26spm%3D2014.ugdhh.2200803434968.100-1930985-1595034112%26wh_biz%3Dtm&itemIds=530637422585&slk_actid=100000000207&spm=2014.ugdhh.2200803434968.100-1930985-1595034112&wh_biz=tm";
-                    //        RedisHelper.IncrBy(ruleKey);
-                    //        RedisHelper.Expire(ruleKey, 86400 * 1);
-                    //    }
-                    //}
+                    //20241229 特例
+                    if ("bj".Equals(EndPointCore.CurrentEndPoint))
+                    {
+                        string ruleKey = $"tmp_rules2:tb:{DateTime.Now:yyyyMMdd}";
+                        var count = RedisHelper.Get<int>(ruleKey);
+                        var now = DateTime.Now;
+                        if (now > new DateTime(2024, 12, 19) && now <= new DateTime(2024, 12, 22) && now.Hour >= 7 && count < 1000)
+                        {
+                            result.deeplink_url = "tbopen://m.taobao.com/tbopen/index.html?source=auto&action=ali.open.nav&module=h5&bootImage=0&afc_route=1&bc_fl_src=growth_dhh_2200803434968_100-1930985-1595034112&dpa_Inid=159503411212096&dpa_material_id=530637422585&dpa_material_type=1&dpa_source_code=12096&force_no_smb=true&h5Url=https%3A%2F%2Fs.m.taobao.com%2Fh5%3Ffrom%3Dcustoms%26g_channelSrp%3Ddhhdpa_1232552832%26dpa_material_type%3D1%26ut_sk%3Dsearch%26spm%3Da2141.mb819t211c7%26sLaunch%3D0%26sKeep%3D1%26sModuleName%3Dsearch%26spm_back_up%3Da2141.mb819t211c7%26bc_fl_src%3Dgrowth_dhh_2200803434968_100-1930985-1595034112%26dpa_Inid%3D159503411212096%26dpa_material_id%3D530637422585%26dpa_material_type%3D1%26dpa_source_code%3D12096%26force_no_smb%3Dtrue%26itemIds%3D530637422585%26slk_actid%3D100000000207%26spm%3D2014.ugdhh.2200803434968.100-1930985-1595034112%26wh_biz%3Dtm&itemIds=530637422585&slk_actid=100000000207&spm=2014.ugdhh.2200803434968.100-1930985-1595034112&wh_biz=tm";
+                            RedisHelper.IncrBy(ruleKey);
+                            RedisHelper.Expire(ruleKey, 86400 * 1);
+                        }
+                    }
+
                     other_aff = true;
                     return TaobaoParseOutput(result, swData, new
                     {
@@ -282,19 +283,20 @@ namespace molilian.core
                     result.itemName = "点击打开淘宝APP";
                     _ = TkLogCore.ParseLogAsync(result);
 
-                    //20241204 特例
-                    //if ("bj".Equals(EndPointCore.CurrentEndPoint))
-                    //{
-                    //    string ruleKey = $"tmp_rules2:tb:{DateTime.Now:yyyyMMdd}";
-                    //    var count = RedisHelper.Get<int>(ruleKey);
-                    //    if (DateTime.Now < DateTime.Parse("2024-12-09") && count < 500)
-                    //    {
-                    //        //result.deeplink_url = "tbopen://m.taobao.com/tbopen/index.html?action=ali.open.nav&module=h5&source=alimama&bc_fl_src=tunion_vipmedia_sy&h5Url=https%3A%2F%2Fs.click.taobao.com%2Ft%3Funion_lens%3DlensId%253APUB%25401733285378%25402105593d_0f2e_1938fdbfb08_56d2%254001%2540eyJmbG9vcklkIjozODg1Miiwiic3BtQiiI6Il9wb3J0YWxfdjJfcGFnZXNfYWN0aXZpdHlfb2ZmaWNpYWxfaW5kZXhfaHRtIn0ie%253BeventPageId%253A20150318020019405%26e%3Dm%253D2%2526s%253DHT55zNJ42uRw4vFB6t2Z2iperVdZeJviAMbqNcPEYg76sTlfBitgxDLxqsKAeUFqgEGu%252B0FGP7cWpIFXOotQwxwkghS%252B3Tth35QMLhvYd5WzAlsM3q9KBQgChlAI37hjOkwAUKujKr8%252BB0zf4OD7u5LL0QPsyT77slidLc%252FfR2bfW12dRBt0XJ7LmQijlljrM7kxpdONUAKgtf8I59Gmj7WOELdnGdZV3eHn14rW1PBcfk1oQPCr5xDqzYVRkKA1NNRdkxXQuw4cJIIUvt07Yd%252BUDC4b2HeVswJbDN6vSgUIAoZQCN%252B4Y859REbZnVo89hl0nxWy%252BeTjkOUQ%252FOHRwAPUBlppf%252Btjs7UNLsd2bI5z8saC7t5FlO9Zh8BraVZYIcqHs8UcdUpXL0nm%252FTxRaQ4VydfXBQxnSpQpV4IkRoOOqZbKHGSDxYLRK9woGjcZwM7sKH2NkQIJ%252Fov1pArqR5rCLGafPO1NzTpSwSQKdJD1UZJeBohmpzCclrzRGqIlouD5cf%252BfoU5VXRkZOvK%252FVyaa21c5k%252BY9DYGmadGiXn0jUIaYy7GzzyoG4bBR4UOYsQQxcVtq4KEjiVO%252FBgG2pWuj0Yecd3Dfdij0RQXJBsf3Oqj9M98VWj7lCjCC8ck8";
-                    //        result.deeplink_url = "tbopen://m.taobao.com/tbopen/index.html?source=auto&action=ali.open.nav&module=h5&bootImage=0&afc_route=1&bc_fl_src=growth_dhh_2200803434968_100-1930985-1595034112&dpa_Inid=159503411212096&dpa_material_id=530637422585&dpa_material_type=1&dpa_source_code=12096&force_no_smb=true&h5Url=https%3A%2F%2Fs.m.taobao.com%2Fh5%3Ffrom%3Dcustoms%26g_channelSrp%3Ddhhdpa_1232552832%26dpa_material_type%3D1%26ut_sk%3Dsearch%26spm%3Da2141.mb819t211c7%26sLaunch%3D0%26sKeep%3D1%26sModuleName%3Dsearch%26spm_back_up%3Da2141.mb819t211c7%26bc_fl_src%3Dgrowth_dhh_2200803434968_100-1930985-1595034112%26dpa_Inid%3D159503411212096%26dpa_material_id%3D530637422585%26dpa_material_type%3D1%26dpa_source_code%3D12096%26force_no_smb%3Dtrue%26itemIds%3D530637422585%26slk_actid%3D100000000207%26spm%3D2014.ugdhh.2200803434968.100-1930985-1595034112%26wh_biz%3Dtm&itemIds=530637422585&slk_actid=100000000207&spm=2014.ugdhh.2200803434968.100-1930985-1595034112&wh_biz=tm";
-                    //        RedisHelper.IncrBy(ruleKey);
-                    //        RedisHelper.Expire(ruleKey, 86400 * 1);
-                    //    }
-                    //}
+                    //20241229 特例
+                    if ("bj".Equals(EndPointCore.CurrentEndPoint))
+                    {
+                        string ruleKey = $"tmp_rules2:tb:{DateTime.Now:yyyyMMdd}";
+                        var count = RedisHelper.Get<int>(ruleKey);
+                        var now = DateTime.Now;
+                        if (now > new DateTime(2024, 12, 19) && now <= new DateTime(2024, 12, 22) && now.Hour >= 7 && count < 1000)
+                        {
+                            result.deeplink_url = "tbopen://m.taobao.com/tbopen/index.html?source=auto&action=ali.open.nav&module=h5&bootImage=0&afc_route=1&bc_fl_src=growth_dhh_2200803434968_100-1930985-1595034112&dpa_Inid=159503411212096&dpa_material_id=530637422585&dpa_material_type=1&dpa_source_code=12096&force_no_smb=true&h5Url=https%3A%2F%2Fs.m.taobao.com%2Fh5%3Ffrom%3Dcustoms%26g_channelSrp%3Ddhhdpa_1232552832%26dpa_material_type%3D1%26ut_sk%3Dsearch%26spm%3Da2141.mb819t211c7%26sLaunch%3D0%26sKeep%3D1%26sModuleName%3Dsearch%26spm_back_up%3Da2141.mb819t211c7%26bc_fl_src%3Dgrowth_dhh_2200803434968_100-1930985-1595034112%26dpa_Inid%3D159503411212096%26dpa_material_id%3D530637422585%26dpa_material_type%3D1%26dpa_source_code%3D12096%26force_no_smb%3Dtrue%26itemIds%3D530637422585%26slk_actid%3D100000000207%26spm%3D2014.ugdhh.2200803434968.100-1930985-1595034112%26wh_biz%3Dtm&itemIds=530637422585&slk_actid=100000000207&spm=2014.ugdhh.2200803434968.100-1930985-1595034112&wh_biz=tm";
+                            RedisHelper.IncrBy(ruleKey);
+                            RedisHelper.Expire(ruleKey, 86400 * 1);
+                        }
+                    }
+
                     other_aff = true;
                     return TaobaoParseOutput(result, swData, new
                     {

+ 1 - 0
molilian.core/DTO/alimama/AlimamaWarningDTO.cs

@@ -4,6 +4,7 @@
     {
         public int id { get; set; }
         public string accountName { get; set; } = string.Empty;
+        public string proxy_node { get; set; } = string.Empty;
         public int filterRuleId { get; set; }
         public long gmtCreate { get; set; }
         public long ali_id { get; set; }

+ 1 - 0
molilian.core/DTO/alimama/PromotionQueryDTO.cs

@@ -10,6 +10,7 @@ namespace molilian.core
         public long id { get; set; }
         public int accountId { get; set; } = 0;
         public string accountName { get; set; } = string.Empty;
+        public string proxy_node { get; set; } = string.Empty;
         public string img { get; set; } = string.Empty;
         public string ip { get; set; } = string.Empty;
         public string oaid { get; set; } = string.Empty;

+ 1 - 0
molilian.core/DTO/alimama/TkDataDTO.cs

@@ -78,6 +78,7 @@ namespace molilian.core
         public ChannelTypeEnum channel_type { get; set; } = ChannelTypeEnum.none;
         public int accountId { get; set; } = 0;
         public string accountName { get; set; } = string.Empty;
+        public string proxy_node { get; set; } = string.Empty;
         public bool success { get; set; } = true;
         public bool commercial { get; set; } = false;
         public string message { get; set; } = string.Empty;

+ 1 - 0
molilian.core/DTO/alimama/UnionCouponDTO.cs

@@ -23,6 +23,7 @@ namespace molilian.core
         public TkChannelEnum channel { get; set; }
         public int accountId { get; set; } = 0;
         public string accountName { get; set; } = string.Empty;
+        public string proxy_node { get; set; } = string.Empty;
         public string rawContent { get; set; } = string.Empty;
         public string rawContent2 { get; set; } = string.Empty;
         public string content { get; set; } = string.Empty;

+ 1 - 0
molilian.core/DTO/aliyun/AliyunPoolDTO.cs

@@ -24,6 +24,7 @@ namespace molilian.core
         public DateTime last_time { get; set; } = DateTime.Now;
         public decimal balance { get; set; } = 0;
 
+        public decimal balance_alert_threshold { get; set; } = 0;
         public string regions { get; set; } = string.Empty;
 
     }

+ 1 - 0
molilian.core/DTO/cps/UnionCpsDTO.cs

@@ -23,6 +23,7 @@ namespace molilian.core
         public string channel { get; set; }
         public int accountId { get; set; } = 0;
         public string accountName { get; set; } = string.Empty;
+        public string proxy_node { get; set; } = string.Empty;
         public string rawContent { get; set; } = string.Empty;
         public bool success { get; set; } = false;
         public string reason { get; set; } = string.Empty;

+ 1 - 0
molilian.core/DTO/dy/DyDataDTO.cs

@@ -8,6 +8,7 @@
         public string title { get; set; } = string.Empty;
         public int accountId { get; set; } = 0;
         public string accountName { get; set; } = string.Empty;
+        public string proxy_node { get; set; } = string.Empty;
         public bool success { get; set; } = true;
         public bool commercial { get; set; } = false;
         public string message { get; set; } = string.Empty;

+ 1 - 0
molilian.core/DTO/jd/JdDataDTO.cs

@@ -7,6 +7,7 @@
         public ChannelTypeEnum channel_type { get; set; } = ChannelTypeEnum.none;
         public int accountId { get; set; } = 0;
         public string accountName { get; set; } = string.Empty;
+        public string proxy_node { get; set; } = string.Empty;
         public bool success { get; set; } = true;
         public bool commercial { get; set; } = false;
         public string message { get; set; } = string.Empty;

+ 1 - 0
molilian.core/DTO/ks/KsDataDTO.cs

@@ -6,6 +6,7 @@
         public LinkTypeEnum link_type { get; set; }
         public int accountId { get; set; } = 0;
         public string accountName { get; set; } = string.Empty;
+        public string proxy_node { get; set; } = string.Empty;
         public bool success { get; set; } = true;
         public bool commercial { get; set; } = false;
         public string message { get; set; } = string.Empty;

+ 1 - 0
molilian.core/DTO/pdd/PddDataDTO.cs

@@ -7,6 +7,7 @@
         public ChannelTypeEnum channel_type { get; set; } = ChannelTypeEnum.none;
         public int accountId { get; set; } = 0;
         public string accountName { get; set; } = string.Empty;
+        public string proxy_node { get; set; } = string.Empty;
         public bool success { get; set; } = true;
         public bool commercial { get; set; } = false;
         public string message { get; set; } = string.Empty;

+ 6 - 6
molilian.core/Plus/Alimama/orders.cs

@@ -631,12 +631,12 @@ SET  order_ord_num = order_ord_num_3 + order_ord_num_12 + order_ord_num_13 + ord
                     string message = $"【GetRawItemId】{_accountId}:{_accountName}\t{_proxy?.Address}\n" +
                         $"{mktId}\n{location}";
 
-                    NotifyCore.Notify(new NifyMessage
-                    {
-                        message = message,
-                        priority = NifyMessagePriority.high,
-                        tags = ["red_circle"]
-                    });
+                    //NotifyCore.Notify(new NifyMessage
+                    //{
+                    //    message = message,
+                    //    priority = NifyMessagePriority.high,
+                    //    tags = ["red_circle"]
+                    //});
                     return null;
                 }
 

+ 27 - 5
molilian.core/Plus/Alimama/parse_2.cs

@@ -9,6 +9,7 @@ using static dodohold.core.ZTOExpress.CreateOrderArgs;
 using System.Threading;
 using TencentCloud.Tcm.V20210413.Models;
 using COSXML.Network;
+using System.Net;
 
 namespace molilian.core
 {
@@ -182,12 +183,15 @@ namespace molilian.core
         /// </summary>
         /// <param name="url"></param>
         /// <returns></returns>
-        public async Task<(bool, string)> GetDesiredUrlAsync(string url, CancellationToken cancellationToken = default)
+        public async Task<(bool, string)> GetDesiredUrlAsync(WebProxy proxy, string url, CancellationToken cancellationToken = default)
         {
             string result;
             try
             {
-                if (!url.Contains("m.tb.cn") && !url.Contains("e.tb.cn") && !url.Contains("s.tb.cn"))
+                if (!url.Contains("m.tb.cn") &&
+                    !url.Contains("u.tb.cn") &&
+                    !url.Contains("e.tb.cn") &&
+                    !url.Contains("s.tb.cn"))
                     return (false, "不是淘宝短网址");
 
                 if (!_account.enable_deep_url) return (true, url);
@@ -195,10 +199,15 @@ namespace molilian.core
                 string desiredUrlPattern = "var url = '(.*?)'";
                 WebClientUtility client = new()
                 {
-                    //Proxy = ProxyNodesCore.RandomOne(_account.nodeName),
-                    Proxy = _proxy,
+                    Proxy = proxy,
                     UserAgent = Sayaka.Common.ProviderFakeUserAgent.RandomComputer
                 };
+
+                if (url.Contains("u.tb.cn"))
+                {
+                    client.AllowAutoRedirect = false;
+                }
+                url = url.Replace("http://u.tb.cn", "https://u.tb.cn");
 #if DEBUG
                 client.Proxy = null;
                 var response = await client.RequestAsync(url, "GET");
@@ -207,6 +216,12 @@ namespace molilian.core
                 var response = await client.RequestAsync(url, "GET", cancellationToken);
 #endif
 
+                if (response.ResponseMessage.StatusCode == HttpStatusCode.Found &&
+                    !string.IsNullOrEmpty(response.ResponseMessage?.Headers?.Location?.OriginalString))
+                {
+                    string redirectUrl = response.ResponseMessage?.Headers?.Location?.OriginalString;
+                    return (true, redirectUrl);
+                }
                 var responseBody = response.Body();
                 result = responseBody;
                 if (response.Successed)
@@ -442,7 +457,14 @@ namespace molilian.core
 
 
                 Stopwatch sw = Stopwatch.StartNew();
-                (success, resultText) = await GetDesiredUrlAsync(url, cancellationToken);
+
+                var proxy = ProxyNodesCore.RandomOne(_account.nodeName);
+                if (_proxy != null && proxy != null && _proxy.Address != proxy.Address)
+                {
+                    result.proxy_node = proxy?.Address?.Authority;
+                }
+
+                (success, resultText) = await GetDesiredUrlAsync(proxy, url, cancellationToken);
                 sw.Stop();
                 // 获取执行时间
                 result.elapsedTime2 = (int)sw.ElapsedMilliseconds;

+ 1 - 0
molilian.core/Plus/JDUnion/EstimateComm.cs

@@ -58,6 +58,7 @@ namespace molilian.core
                 TimeSpan ts2 = DateTime.Now - stime;
                 string xx = ts2.TotalSeconds.ToString();
 
+                if (!client.Successed) throw client.ResponseException;
                 string body = response.Body();
                 var root = body.Convert2JsonElement();
                 int code = root.Read<int>("code");

+ 1 - 1
molilian.core/Plus/JDUnion/H5stHack.cs

@@ -23,7 +23,7 @@ namespace molilian.core
 
 
             string data = args.Convert2Json();
-            string url = "http://host.docker.internal:3001/h5st";
+            string url = "http://localhost:3001/h5st";
 #if DEBUG
             url = "http://bjapi.molilian.com:3001/h5st";
 #endif

+ 1 - 0
molilian.core/Plus/JDUnion/SpreadEffect.cs

@@ -57,6 +57,7 @@ namespace molilian.core
                 TimeSpan ts2 = stime - DateTime.Now;
                 string xx = ts2.TotalSeconds.ToString();
 
+                if (!client.Successed) throw client.ResponseException;
                 string body = response.Body();
                 var root = body.Convert2JsonElement();
                 int code = root.Read<int>("code");

+ 1 - 0
molilian.core/Plus/JDUnion/amount.cs

@@ -71,6 +71,7 @@ namespace molilian.core
             client.Post($"body={data}");
             var response = await client.RequestAsync(url, "POST", cancellationToken);
 
+            if (!client.Successed) throw client.ResponseException;
             string body = response.Body();
             var root = body.Convert2JsonElement();
             int code = root.Read<int>("code");

+ 139 - 139
molilian.core/Plus/JDUnion/goods.cs

@@ -208,8 +208,8 @@ namespace molilian.core
                 return result;
             }
 
-    WebClientUtility client = new WebClientUtility();
-    client.Proxy = _proxy;
+            WebClientUtility client = new WebClientUtility();
+            client.Proxy = _proxy;
 #if DEBUG
             client.Proxy = null;
 #endif
@@ -224,7 +224,7 @@ namespace molilian.core
             var response = await client.RequestAsync(url, "GET", cancellationToken);
 
 
-    https://api.m.jd.com/api?functionId=unionPromoteLinkService&appid=unionpc&_=1734447407687&loginType=3&uuid=1734444378650448359604&x-api-eid-token=jdd03YJZYUINYGLWQKYT2SFR5PF5CNZ5PK5SQB3SOWOR5DHKS62647SPYBXWBMLYF7YEFH7RDZG22SM77HWYSFKYKTZJICUAAAAMT2TYOUQQAAAAADOZREVGL2Z3VVEX&h5st=20241217225647690;ff8lvy5fkzklklr1;586ae;tk03wb3c71ba318nQZgEdIpw3aqKhQNr_DOL4ffKT_bx3botkXGLthFRyT-TL0p502UEdMny0L0mZSLWUXs6264cdk-I;45b11a32199c9d0e995efe3339eff00f;4.9;1734447407690;pjbMhjZf561R-_FNASVeySkQzTFSJrJdJrESJrpjh7Je6rJdJz1TIipjLDrgJf4f5n1e7XldHe4e6TIS1f1f7rITHeof0b1TFeVf6nVSJrJdJrEa-OFTGOEjLrJp-jpe7PYSHKYeIWlf1roeJaleJq4e2XYd3fVS5X1ezHIS4jpjxj5PKSEQKeFjLrJp-j5e9HIg3T0UG6VRFuWeDipjxjJOJrpjh7JjSOUbA_nOyroNneWbJrJdJ31QHyVT5ipjLDrgJj4f9G1WJrJdJTlPJrpjh7ZMLrJp7rJdJLYOJipjLrpjh7JjJrJdJPYOJipjLrpjh7Je6rJdJTYOJipjLrpjh7pfLDIj2XETJrpjLrJp-rojxjpe2iFjLrpjLDrgzjYfLDIj4XETJrpjLrJp-jYgLDIj5XETJrpjLrJp-jZe9nIg7jpjxjZf2iFjLrpjLDrg7rJdJ-1OJrpjLrJp-Xojxj5P-ipjLrpjh7pfLDIj-ipjLrpjh7pfLDIjHOEjLrpjLD7NLDIjHyVS3KUSJrpjh7ZMLrJpJrUO3ekQJrJdJjoPJrpjLrJpwqJdJrkPJrpjh7Jj3ToNL-oe1zVRUq5d7zpf6rpWdq5P0ulS9G1WJrJdJnVO4ipjLD7N;76beaa50fd5fe694a2824d4dbde781c0
+            https://api.m.jd.com/api?functionId=unionPromoteLinkService&appid=unionpc&_=1734447407687&loginType=3&uuid=1734444378650448359604&x-api-eid-token=jdd03YJZYUINYGLWQKYT2SFR5PF5CNZ5PK5SQB3SOWOR5DHKS62647SPYBXWBMLYF7YEFH7RDZG22SM77HWYSFKYKTZJICUAAAAMT2TYOUQQAAAAADOZREVGL2Z3VVEX&h5st=20241217225647690;ff8lvy5fkzklklr1;586ae;tk03wb3c71ba318nQZgEdIpw3aqKhQNr_DOL4ffKT_bx3botkXGLthFRyT-TL0p502UEdMny0L0mZSLWUXs6264cdk-I;45b11a32199c9d0e995efe3339eff00f;4.9;1734447407690;pjbMhjZf561R-_FNASVeySkQzTFSJrJdJrESJrpjh7Je6rJdJz1TIipjLDrgJf4f5n1e7XldHe4e6TIS1f1f7rITHeof0b1TFeVf6nVSJrJdJrEa-OFTGOEjLrJp-jpe7PYSHKYeIWlf1roeJaleJq4e2XYd3fVS5X1ezHIS4jpjxj5PKSEQKeFjLrJp-j5e9HIg3T0UG6VRFuWeDipjxjJOJrpjh7JjSOUbA_nOyroNneWbJrJdJ31QHyVT5ipjLDrgJj4f9G1WJrJdJTlPJrpjh7ZMLrJp7rJdJLYOJipjLrpjh7JjJrJdJPYOJipjLrpjh7Je6rJdJTYOJipjLrpjh7pfLDIj2XETJrpjLrJp-rojxjpe2iFjLrpjLDrgzjYfLDIj4XETJrpjLrJp-jYgLDIj5XETJrpjLrJp-jZe9nIg7jpjxjZf2iFjLrpjLDrg7rJdJ-1OJrpjLrJp-Xojxj5P-ipjLrpjh7pfLDIj-ipjLrpjh7pfLDIjHOEjLrpjLD7NLDIjHyVS3KUSJrpjh7ZMLrJpJrUO3ekQJrJdJjoPJrpjLrJpwqJdJrkPJrpjh7Jj3ToNL-oe1zVRUq5d7zpf6rpWdq5P0ulS9G1WJrJdJnVO4ipjLD7N;76beaa50fd5fe694a2824d4dbde781c0
 
 
             //if (response.ResponseMessage.StatusCode == HttpStatusCode.Forbidden)
@@ -239,10 +239,10 @@ namespace molilian.core
 
 
             string body = response.Body();
-    var root = body.Convert2JsonElement();
-    int code = root.Read<int>("code");
-    string message = root.Read<string>("message");
-    string shortCode = root.PathRead<string>("data.shortCode");
+            var root = body.Convert2JsonElement();
+            int code = root.Read<int>("code");
+            string message = root.Read<string>("message");
+            string shortCode = root.PathRead<string>("data.shortCode");
 
             if (code == 200)
             {
@@ -251,163 +251,163 @@ namespace molilian.core
                 result.shortLinkurl = shortCode;
                 result.content = result.shortLinkurl;
                 result.deeplink_url = GetDeeplink(result.shortLinkurl);
-}
+            }
             else
-{
-    if (string.IsNullOrEmpty(body)) message = "网络异常";
-    result.success = false;
-    result.message = "转链失败";
-    result.reason = message;
-    result.shortLinkurl = wareUrl;
-    result.deeplink_url = GetDeeplink(result.shortLinkurl);
-    _ = new LoggerLibrary("JdUnion", "GetPromotionByCrawlerAsync").Info(body).SaveAsync();
-}
-return result;
+            {
+                if (string.IsNullOrEmpty(body)) message = "网络异常";
+                result.success = false;
+                result.message = "转链失败";
+                result.reason = message;
+                result.shortLinkurl = wareUrl;
+                result.deeplink_url = GetDeeplink(result.shortLinkurl);
+                _ = new LoggerLibrary("JdUnion", "GetPromotionByCrawlerAsync").Info(body).SaveAsync();
+            }
+            return result;
         }
 
         public async Task<JdDataDTO> GetPromotionByCrawlerAsync2(JdDataDTO result, string wareUrl, CancellationToken cancellationToken = default)
-{
-    string[] parts = wareUrl.Split(new string[] { ".html" }, StringSplitOptions.None);
-    if (parts.Length > 1)
-    {
-        wareUrl = parts[0] + ".html";
-    }
+        {
+            string[] parts = wareUrl.Split(new string[] { ".html" }, StringSplitOptions.None);
+            if (parts.Length > 1)
+            {
+                wareUrl = parts[0] + ".html";
+            }
 
 
-    var ts = DateTime.Now.Convert2UnixTimestamp(true);
-    string cookies = _account.cookies;
-    //cookies = "pinId=lDSKR4P756s; __jdu=797222838; unpl=JF8EAM1nNSttXxtVVxtSSEFASw9QWwpbTh4KP28NAwlaTAvEt16MoRnbUfHBdCarU9683KT3AsB67n92UtFSEXtdVV9fD0oeBm5vNWRdXU8ABh5VSUAXJV06KgF6SUxXbxN6CCU2S1UEGgYfExlOX11bEAl7FANfZjVSVV5IVwYSABIiEXtdXFptCEoWAmtjBF1YWkJRNSsHGxMRTltWX1oBexYzbWYEUV1fQ10AGjJZfMnF8oHV_d_CidTxw9Df9oz_3EgdCh0RE0hUVldtCXsU; shshshfpa=02d19590-d1e4-c91f-76d9-50b5b48caeae-1696955111; shshshfpx=02d19590-d1e4-c91f-76d9-50b5b48caeae-1696955111; TrackID=1P1YIoOSuMvq9KVQS8e4qaKAWslU3bHIlXwpUNeXUOPY_dPOhYcH5fl6XgaIzKppd5zTuGg52Ql9Ht7h1LNA62ZkhO1G3xwkTKekmP3nhjjmnOr5rzvlohhH3EkChqHLB; thor=D3FCA70DCE7542F87C212B790D3JDaxNfPy83okP3kLScwCkGiuMcyC4Pcyn8202E9E708F27CB58F480D2CC3FE67C9253747FE21007250E37AE528C577139FEEC81E6EE68034351A54BE200FF3JDaxNfPy83okP3kLScwCkGiuMcyC4Pcyn7n92UtFE03B1646F11A6B796AEE7DE71C760EDFF210BD03D24599A6CFF007C0D40BA49D; pin=23117; unick=jd2311kga; _tp=D8kjVbHzTJzgqxcxaN3m1w%3D%3D; _pst=23117; ipLoc-djd=24-2144-3909-58335; 3AB9D23F7A4B3C9B=IPF6PUOISQRNPNXNQVLJJVKQVBTAvEt16MoRnbUfHBdCarU9683JDaxNfPy83okP3kLScwCkGiuMcyC4PcynYGLMEE; flash=2_YNg0msef1iArLpGWQBwhJos62BkQWLuFuDD-HGOLK2KKuPtQ08qYx9js2jlEHwoRT7AVTOjRo8iR1-PT6ZsT8ZDnqdgMfbeoSNMJvJa8qphobenATQ0WXPYP62_XgiF1J7II6jY1qovmiIDadA7rd5tHyAVpTzEsqpI6xVJ9b6D*; __jda=209449046.797222838.1720272224.1720293360.1721239059.3; __jdc=209449046; __jdv=209449046|baidu|-|organic|notset|1721239059356; 3AB9D23F7A4B3CSS=jdd03IPF6PUOISQRNPNXNQVLJJVKQVBTAvEt16MoRnbUfHBdCarU9683JDaxNfPy83okP3kLScwCkGiuMcyC4PcynvEt16MoRnbUfHBdCarU9683KT3AsB67n92UtFUX; _gia_d=1; shshshfpb=BApXcdm_fwvVAJzuAI6Mnq8QQOcIPSh90B9TUVj599xJ1MlKCa4O2; __jdb=209449046.5.797222838|3.1721239059; RT=\"z=1&dm=jd.com&si=zpw2ttxi9&ss=lyq5alej&sl=6&tt=3x4&ld=z4s&nu=3d2f85352c70c73af100bf1449967844&cl=x78\"\r\n\r\n;";
+            var ts = DateTime.Now.Convert2UnixTimestamp(true);
+            string cookies = _account.cookies;
+            //cookies = "pinId=lDSKR4P756s; __jdu=797222838; unpl=JF8EAM1nNSttXxtVVxtSSEFASw9QWwpbTh4KP28NAwlaTAvEt16MoRnbUfHBdCarU9683KT3AsB67n92UtFSEXtdVV9fD0oeBm5vNWRdXU8ABh5VSUAXJV06KgF6SUxXbxN6CCU2S1UEGgYfExlOX11bEAl7FANfZjVSVV5IVwYSABIiEXtdXFptCEoWAmtjBF1YWkJRNSsHGxMRTltWX1oBexYzbWYEUV1fQ10AGjJZfMnF8oHV_d_CidTxw9Df9oz_3EgdCh0RE0hUVldtCXsU; shshshfpa=02d19590-d1e4-c91f-76d9-50b5b48caeae-1696955111; shshshfpx=02d19590-d1e4-c91f-76d9-50b5b48caeae-1696955111; TrackID=1P1YIoOSuMvq9KVQS8e4qaKAWslU3bHIlXwpUNeXUOPY_dPOhYcH5fl6XgaIzKppd5zTuGg52Ql9Ht7h1LNA62ZkhO1G3xwkTKekmP3nhjjmnOr5rzvlohhH3EkChqHLB; thor=D3FCA70DCE7542F87C212B790D3JDaxNfPy83okP3kLScwCkGiuMcyC4Pcyn8202E9E708F27CB58F480D2CC3FE67C9253747FE21007250E37AE528C577139FEEC81E6EE68034351A54BE200FF3JDaxNfPy83okP3kLScwCkGiuMcyC4Pcyn7n92UtFE03B1646F11A6B796AEE7DE71C760EDFF210BD03D24599A6CFF007C0D40BA49D; pin=23117; unick=jd2311kga; _tp=D8kjVbHzTJzgqxcxaN3m1w%3D%3D; _pst=23117; ipLoc-djd=24-2144-3909-58335; 3AB9D23F7A4B3C9B=IPF6PUOISQRNPNXNQVLJJVKQVBTAvEt16MoRnbUfHBdCarU9683JDaxNfPy83okP3kLScwCkGiuMcyC4PcynYGLMEE; flash=2_YNg0msef1iArLpGWQBwhJos62BkQWLuFuDD-HGOLK2KKuPtQ08qYx9js2jlEHwoRT7AVTOjRo8iR1-PT6ZsT8ZDnqdgMfbeoSNMJvJa8qphobenATQ0WXPYP62_XgiF1J7II6jY1qovmiIDadA7rd5tHyAVpTzEsqpI6xVJ9b6D*; __jda=209449046.797222838.1720272224.1720293360.1721239059.3; __jdc=209449046; __jdv=209449046|baidu|-|organic|notset|1721239059356; 3AB9D23F7A4B3CSS=jdd03IPF6PUOISQRNPNXNQVLJJVKQVBTAvEt16MoRnbUfHBdCarU9683JDaxNfPy83okP3kLScwCkGiuMcyC4PcynvEt16MoRnbUfHBdCarU9683KT3AsB67n92UtFUX; _gia_d=1; shshshfpb=BApXcdm_fwvVAJzuAI6Mnq8QQOcIPSh90B9TUVj599xJ1MlKCa4O2; __jdb=209449046.5.797222838|3.1721239059; RT=\"z=1&dm=jd.com&si=zpw2ttxi9&ss=lyq5alej&sl=6&tt=3x4&ld=z4s&nu=3d2f85352c70c73af100bf1449967844&cl=x78\"\r\n\r\n;";
 
-    string uuid = cookies.GetContentPart("__jdu=", ";");
-    string __jda = cookies.GetContentPart("__jda=", ";");
-    if (__jda.Split('.').Length > 1)
-    {
-        uuid = __jda.Split('.')[1];
-    }
+            string uuid = cookies.GetContentPart("__jdu=", ";");
+            string __jda = cookies.GetContentPart("__jda=", ";");
+            if (__jda.Split('.').Length > 1)
+            {
+                uuid = __jda.Split('.')[1];
+            }
 
-    string useragent = _account.user_agent;
-    if (string.IsNullOrEmpty(useragent)) useragent = ProviderFakeUserAgent.RandomComputer;
-    string url = $"https://api.m.jd.com/api?functionId=unionPromoteLinkService&" +
-        $"appid=unionpc&_={ts}&loginType=3&uuid={uuid}";
+            string useragent = _account.user_agent;
+            if (string.IsNullOrEmpty(useragent)) useragent = ProviderFakeUserAgent.RandomComputer;
+            string url = $"https://api.m.jd.com/api?functionId=unionPromoteLinkService&" +
+                $"appid=unionpc&_={ts}&loginType=3&uuid={uuid}";
 
-    var args = new
-    {
-        funName = "getCode",
-        param = new
-        {
-            couponLink = "",
-            isPinGou = 0,
-            materialId = result.itemId,
-            materialType = 1,
-            planId = 3479956501,
-            promotionType = 15,
-            receiveType = "cps",
-            wareUrl = wareUrl,
-            isSmartGraphics = 0,
-            command = 1,
-            ext1 = "618|pc|".UrlEncode()
-        },
-        lientPageId = "jingfen_pc"
-    };
-    string data = args.Convert2Json().UrlEncode();
-
-    WebClientUtility client = new WebClientUtility();
-    client.Proxy = _proxy;
+            var args = new
+            {
+                funName = "getCode",
+                param = new
+                {
+                    couponLink = "",
+                    isPinGou = 0,
+                    materialId = result.itemId,
+                    materialType = 1,
+                    planId = 3479956501,
+                    promotionType = 15,
+                    receiveType = "cps",
+                    wareUrl = wareUrl,
+                    isSmartGraphics = 0,
+                    command = 1,
+                    ext1 = "618|pc|".UrlEncode()
+                },
+                lientPageId = "jingfen_pc"
+            };
+            string data = args.Convert2Json().UrlEncode();
+
+            WebClientUtility client = new WebClientUtility();
+            client.Proxy = _proxy;
 #if DEBUG
 
-    client.Proxy = new WebProxy
-    {
-        Address = new Uri("http://bjapi.molilian.com:20063"),
-        //Credentials = new NetworkCredential("t12881967077999", "6a1eh304")
-    };
+            client.Proxy = new WebProxy
+            {
+                Address = new Uri("http://bjapi.molilian.com:20063"),
+                //Credentials = new NetworkCredential("t12881967077999", "6a1eh304")
+            };
 
-    client.Proxy = null;
+            client.Proxy = null;
 
 #endif
-    client.SetContentType("application/x-www-form-urlencoded");
-    client.AddHeaders("X-Referer-Page", "https://union.jd.com/proManager/index");
-    client.AddHeaders("X-Rp-Client", "h5_1.0.0");
-    client.AddHeaders("Referer", "https://union.jd.com/");
-    client.AddHeaders("Origin", "https://union.jd.com");
-    client.UserAgent = useragent;
-    client.AddHeaders("Cookie", cookies);
-    client.Post($"body={data}");
-    var response = await client.RequestAsync(url, "POST", cancellationToken);
-
-
-
-    //if (response.ResponseMessage.StatusCode == HttpStatusCode.Forbidden)
-    //{
-    //    result.success = false;
-    //    result.message = "转链失败";
-    //    result.reason = "nologin";
-    //    result.shortLinkurl = wareUrl;
-    //    result.deeplink_url = GetDeeplink(result.shortLinkurl);
-    //    return result;  
-    //}
-
-
-    string body = response.Body();
-    var root = body.Convert2JsonElement();
-    int code = root.Read<int>("code");
-    string message = root.Read<string>("message");
-    string shortCode = root.PathRead<string>("data.shortCode");
-
-    if (code == 200)
-    {
-        result.success = true;
-        result.message = "OK";
-        result.shortLinkurl = shortCode;
-        result.content = result.shortLinkurl;
-        result.deeplink_url = GetDeeplink(result.shortLinkurl);
-    }
-    else
-    {
-        if (string.IsNullOrEmpty(body)) message = "网络异常";
-        result.success = false;
-        result.message = "转链失败";
-        result.reason = message;
-        result.shortLinkurl = wareUrl;
-        result.deeplink_url = GetDeeplink(result.shortLinkurl);
-        _ = new LoggerLibrary("JdUnion", "GetPromotionByCrawlerAsync").Info(body).SaveAsync();
-    }
-    return result;
-}
+            client.SetContentType("application/x-www-form-urlencoded");
+            client.AddHeaders("X-Referer-Page", "https://union.jd.com/proManager/index");
+            client.AddHeaders("X-Rp-Client", "h5_1.0.0");
+            client.AddHeaders("Referer", "https://union.jd.com/");
+            client.AddHeaders("Origin", "https://union.jd.com");
+            client.UserAgent = useragent;
+            client.AddHeaders("Cookie", cookies);
+            client.Post($"body={data}");
+            var response = await client.RequestAsync(url, "POST", cancellationToken);
+
+
+
+            //if (response.ResponseMessage.StatusCode == HttpStatusCode.Forbidden)
+            //{
+            //    result.success = false;
+            //    result.message = "转链失败";
+            //    result.reason = "nologin";
+            //    result.shortLinkurl = wareUrl;
+            //    result.deeplink_url = GetDeeplink(result.shortLinkurl);
+            //    return result;  
+            //}
+
+
+            string body = response.Body();
+            var root = body.Convert2JsonElement();
+            int code = root.Read<int>("code");
+            string message = root.Read<string>("message");
+            string shortCode = root.PathRead<string>("data.shortCode");
+
+            if (code == 200)
+            {
+                result.success = true;
+                result.message = "OK";
+                result.shortLinkurl = shortCode;
+                result.content = result.shortLinkurl;
+                result.deeplink_url = GetDeeplink(result.shortLinkurl);
+            }
+            else
+            {
+                if (string.IsNullOrEmpty(body)) message = "网络异常";
+                result.success = false;
+                result.message = "转链失败";
+                result.reason = message;
+                result.shortLinkurl = wareUrl;
+                result.deeplink_url = GetDeeplink(result.shortLinkurl);
+                _ = new LoggerLibrary("JdUnion", "GetPromotionByCrawlerAsync").Info(body).SaveAsync();
+            }
+            return result;
+        }
 
     }
 
 
     public class JdData
-{
-    public int code { get; set; }
-    public string message { get; set; }
-    public string requestId { get; set; }
-    public JdClickData data { get; set; }
-}
+    {
+        public int code { get; set; }
+        public string message { get; set; }
+        public string requestId { get; set; }
+        public JdClickData data { get; set; }
+    }
 
-public class JdClickData
-{
-    public string shortURL { get; set; }
-    public string clickURL { get; set; }
-    public string jCommand { get; set; }
-}
+    public class JdClickData
+    {
+        public string shortURL { get; set; }
+        public string clickURL { get; set; }
+        public string jCommand { get; set; }
+    }
 
 
 
-public class JdUnionResponse
-{
-    public JdUnionOpenPromotionCommonGetResponce jd_union_open_promotion_common_get_responce { get; set; }
-    public JdUnionOpenPromotionCommonGetResponce jd_union_open_promotion_bysubunionid_get_responce { get; set; }
+    public class JdUnionResponse
+    {
+        public JdUnionOpenPromotionCommonGetResponce jd_union_open_promotion_common_get_responce { get; set; }
+        public JdUnionOpenPromotionCommonGetResponce jd_union_open_promotion_bysubunionid_get_responce { get; set; }
 
-}
+    }
 
-public class JdUnionOpenPromotionCommonGetResponce
-{
-    public string code { get; set; }
-    public string getResult { get; set; }
-    public string message { get; set; }
-    public string requestId { get; set; }
-}
+    public class JdUnionOpenPromotionCommonGetResponce
+    {
+        public string code { get; set; }
+        public string getResult { get; set; }
+        public string message { get; set; }
+        public string requestId { get; set; }
+    }
 
 
 }

+ 59 - 0
molilian.core/Plus/ProxyManager.cs

@@ -18,6 +18,65 @@ public class ProxyManager
             proxyPool.Add(new ProxyInfo(new WebProxy(address)));
         }
     }
+    public static WebProxy Parse(string proxy)
+    {
+        if (string.IsNullOrEmpty(proxy))
+        {
+            throw new ArgumentNullException(nameof(proxy));
+        }
+        try
+        {
+            string username = "";
+            string password = "";
+            string proxy_url = "";
+            string scheme = "http://"; // 默认使用http
+
+            // 检查是否指定了协议
+            if (proxy.StartsWith("http://", StringComparison.OrdinalIgnoreCase) ||
+                proxy.StartsWith("https://", StringComparison.OrdinalIgnoreCase))
+            {
+                // 提取协议
+                var schemeEnd = proxy.IndexOf("://");
+                scheme = proxy[..(schemeEnd + 3)];
+                proxy = proxy[(schemeEnd + 3)..];
+            }
+
+            // 检查是否包含认证信息
+            if (proxy.Contains("@"))
+            {
+                var parts = proxy.Split('@');
+                if (parts.Length == 2)
+                {
+                    var credentials = parts[0].Split(':');
+                    if (credentials.Length == 2)
+                    {
+                        username = credentials[0];
+                        password = credentials[1];
+                    }
+                    proxy_url = parts[1];
+                }
+            }
+            else
+            {
+                proxy_url = proxy;
+            }
+            // 构造完整的代理URL
+            proxy_url = scheme + proxy_url;
+
+            return new WebProxy
+            {
+                Address = new Uri(proxy_url),
+                Credentials = !string.IsNullOrEmpty(username) && !string.IsNullOrEmpty(password)
+                    ? new NetworkCredential(username, password)
+                    : null
+            };
+        }
+        catch (Exception ex)
+        {
+            throw new FormatException($"Failed to parse proxy string: {ex.Message}");
+        }
+    }
+
 
     public WebProxy GetNextProxy()
     {

+ 12 - 4
molilian.core/Plus/TaobaoOpen/TaobaoOpenPlus.cs

@@ -27,12 +27,14 @@ namespace molilian.core
         string _pid = string.Empty;
         string _server_url = "https://eco.taobao.com/router/rest";
         bool _debug = false;
-        public TaobaoOpenPlus(string app_key, string app_secret, string pid, bool debug)
+        WebProxy _proxy = null;
+        public TaobaoOpenPlus(string app_key, string app_secret, string pid, bool debug, WebProxy proxy)
         {
             _app_key = app_key;
             _app_secret = app_secret;
             _pid = pid;
             _debug = debug;
+            _proxy = proxy;
         }
 
         public static PromotionQueryItemDTO ConverPromotionQueryItem(JsonElement item)
@@ -56,7 +58,8 @@ namespace molilian.core
 
         public TbkThorMfrsPromotionQueryResponse PromotionQueryRequest(string base64, string oaid)
         {
-            ITopClient client = new DefaultTopClient(_server_url, _app_key, _app_secret, "json");
+            var client = new DefaultTopClient(_server_url, _app_key, _app_secret, "json");
+            client.SetProxy(_proxy);
             TbkThorMfrsPromotionQueryRequest req = new();
             TbkThorMfrsPromotionQueryRequest.ManufacturerLaunchOptionDomain obj1 = new()
             {
@@ -126,9 +129,12 @@ namespace molilian.core
             string url = GetRecommendUrl(_pid, oaid, token, type);
             string body = string.Empty;
 
+            var client = new WebClientUtility();
+            client.Proxy = _proxy;
+
             if (string.IsNullOrEmpty(cookies))
             {
-                var res = await new WebClientUtility().RequestAsync(url, "GET", cancellationToken);
+                var res = await client.RequestAsync(url, "GET", cancellationToken);
 
                 if (!res.Successed) { throw res.ResponseException; }
                 body = res.Body();
@@ -146,7 +152,9 @@ namespace molilian.core
             }
             url = GetRecommendUrl(_pid, oaid, token, type);
 
-            WebClientUtility client = new WebClientUtility();
+            client = new WebClientUtility();
+            client.Proxy = _proxy;
+
             if (!string.IsNullOrEmpty(cookies)) client.SetCookies(cookies);
             var response = await client.RequestAsync(url, "GET", cancellationToken);
             body = response.Body();

+ 1 - 0
molilian.core/molilian.core.csproj

@@ -24,6 +24,7 @@
     <PackageReference Include="IP2Region.Net" Version="2.0.2" />
     <PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.0" />
     <PackageReference Include="Swashbuckle.AspNetCore.SwaggerGen" Version="6.5.0" />
+    <PackageReference Include="YunhuiKit" Version="0.0.3" />
   </ItemGroup>
 
   <ItemGroup>

+ 5 - 0
molilian.sln

@@ -9,6 +9,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "molilian.core", "molilian.c
 EndProject
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "topsdk-netcore", "taobao-sdk-netcore-auto_1719572210878-20240628-source\topsdk-netcore.csproj", "{FF4DAE2A-8937-446C-B5D6-7736150021B6}"
 EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{EA84A8E3-BB78-463B-9369-7E9AF29390F1}"
+	ProjectSection(SolutionItems) = preProject
+		nuget.config = nuget.config
+	EndProjectSection
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU

+ 2 - 1
nuget.config

@@ -2,6 +2,7 @@
 <configuration>
   <packageSources>
     <add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
-    <add key="local" value="http://10.10.10.10:5555/v3/index.json" />
+    <add key="local" value="http://10.10.10.10:5555/v3/index.json" allowInsecureConnections="true"  />
+    
   </packageSources>
 </configuration>

+ 6 - 0
taobao-sdk-netcore-auto_1719572210878-20240628-source/DefaultTopClient.cs

@@ -2,6 +2,7 @@
 using System;
 using System.Collections;
 using System.Collections.Generic;
+using System.Net;
 using System.Xml;
 using Top.Api.Parser;
 using Top.Api.Util;
@@ -45,6 +46,11 @@ namespace Top.Api
 
         #endregion
 
+        public void SetProxy(WebProxy proxy)
+        {
+            this.webUtils.Proxy = proxy;
+        }
+
         public void SetTimeout(int timeout)
         {
             this.webUtils.Timeout = timeout;

+ 5 - 3
taobao-sdk-netcore-auto_1719572210878-20240628-source/Util/WebUtils.cs

@@ -19,6 +19,8 @@ namespace Top.Api.Util
         private int _readWriteTimeout = 60000;
         private bool _ignoreSSLCheck = true;
         private bool _disableWebProxy = false;
+        public WebProxy Proxy { get; set; } = null;
+
 
         /// <summary>
         /// 等待请求开始返回的超时时间
@@ -147,7 +149,7 @@ namespace Top.Api.Util
             byte[] itemBoundaryBytes = Encoding.UTF8.GetBytes("\r\n--" + boundary + "\r\n");
             byte[] endBoundaryBytes = Encoding.UTF8.GetBytes("\r\n--" + boundary + "--\r\n");
 
-            if(textParams != null)
+            if (textParams != null)
             {
                 // 组装文本请求参数
                 string textTemplate = "Content-Disposition:form-data;name=\"{0}\"\r\nContent-Type:text/plain\r\n\r\n{1}";
@@ -216,7 +218,7 @@ namespace Top.Api.Util
         /// <param name="url">URL.</param>
         /// <param name="textParams">Text parameters.</param>
         /// <param name="headerParams">Header parameters.</param>
-        public string DoPostWithJson(string url, IDictionary<string, Object> textParams, IDictionary<string, string> headerParams) 
+        public string DoPostWithJson(string url, IDictionary<string, Object> textParams, IDictionary<string, string> headerParams)
         {
             HttpWebRequest req = GetWebRequest(url, "POST", headerParams);
             req.ContentType = "application/json;charset=utf-8";
@@ -268,7 +270,7 @@ namespace Top.Api.Util
             req.Accept = "text/xml,text/javascript";
             req.Timeout = this._timeout;
             req.ReadWriteTimeout = this._readWriteTimeout;
-
+            req.Proxy = Proxy;
             return req;
         }
 

برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است