dodo hold před 1 rokem
rodič
revize
6d83381665

+ 134 - 0
molilian.api/Controllers/admin/AliyunController.cs

@@ -0,0 +1,134 @@
+using molilian.core;
+using dodohold.core;
+using Microsoft.AspNetCore.Mvc;
+using System.Text.Json;
+using static molilian.core.ChartDataCore;
+using TencentCloud.Soe.V20180724.Models;
+namespace molilian.api.Controllers
+{
+    [ApiController]
+    [MyAuthorize("admin")]
+    [Route("api/[controller]/[action]")]
+    public class AliyunController : ControllerBase
+    {
+        readonly IAuthorizationProvider provider = new AdminProvider();
+        protected IHttpContextAccessor _accessor;
+        public AliyunController(IHttpContextAccessor accessor)
+        {
+            _accessor = accessor;
+        }
+
+        [HttpPost]
+        public ActionResult account_list([FromBody] JsonElement form)
+        {
+            var token = provider.Get(_accessor.HttpContext);
+
+            int page = form.Read("current", 1);
+            int size = form.Read("pageSize", 10);
+            bool getTotal = form.Read("getTotal", true);
+
+            string sort = form.Read<string>("sort");
+            string order = form.Read<string>("order");
+
+            string filter = string.Empty;
+
+            var keyword = form.Read("keyword", string.Empty);
+
+            if (!string.IsNullOrEmpty(keyword))
+            {
+                filter += $" AND (name like @keyword OR username like @keyword OR company like @keyword OR mobile like @keyword)";
+                keyword = $"%{keyword}%";
+            } 
+            filter = filter.StringTrimStart(" AND ");
+
+            //排序
+            string orderBy = "id DESC";
+            if (!string.IsNullOrEmpty(order))
+            {
+                order = "descending".Equals(order) ? "DESC" : "ASC";
+                orderBy = sort switch
+                {
+                    _ => $"{sort} {order}",
+                };
+            }
+
+            var result = new DBContext.Table("aliyun_pool")
+               .Where(filter, new { keyword })
+               .Page(size, page)
+               .Order(orderBy)
+               .PageList<dynamic>(getTotal);
+             
+            return new APIResult(new { data = result });
+        }
+
+        [HttpPost]
+        public ActionResult ecs_list([FromBody] JsonElement form)
+        {
+            var token = provider.Get(_accessor.HttpContext);
+
+            int page = form.Read("current", 1);
+            int size = form.Read("pageSize", 10);
+            bool getTotal = form.Read("getTotal", true);
+
+            string sort = form.Read<string>("sort");
+            string order = form.Read<string>("order");
+
+            string filter = string.Empty;
+
+            var log_date = form.PathReadArray<string>("query_date[]");
+            var accountName = form.Read("accountName", string.Empty);
+            int channel = form.Read("channel", -1);
+
+            if (!string.IsNullOrEmpty(accountName))
+            {
+                filter += $" AND accountName=@accountName";
+            }
+            else
+            {
+                filter += $" AND accountName!='all'";
+            }
+            DateTime stime = DateTime.MinValue, etime = DateTime.MinValue;
+            if (log_date.Count == 2)
+            {
+                if (DateTime.TryParse(log_date[0], out stime) && DateTime.TryParse(log_date[1], out etime))
+                {
+                    etime = etime.AddDays(1).AddSeconds(-1);
+                    if (etime > DateTime.Now) etime = DateTime.Now;
+                    filter += $" AND log_date BETWEEN @stime AND @etime";
+                }
+            }
+            if (channel != -1)
+            {
+                filter += $" AND channel=@channel";
+            }
+            filter = filter.StringTrimStart(" AND ");
+
+            //排序
+            string orderBy = "id DESC";
+            if (!string.IsNullOrEmpty(order))
+            {
+                order = "descending".Equals(order) ? "DESC" : "ASC";
+                orderBy = sort switch
+                {
+                    _ => $"{sort} {order}",
+                };
+            }
+
+            using var conn = CenterHub.GetOpenConnection();
+            var result = new DBContext.Table(conn, "center_daily_logs")
+                .Where(filter, new { channel, accountName, stime, etime })
+                .Page(size, page)
+                .Order(orderBy)
+                .PageList<DailyLogsDTO>(getTotal);
+
+
+            var accounts = JdPoolCore.List();
+            var hide_ids = accounts.Where(e => e.is_hide).Select(e => e.id).ToList();
+            result.List = result.List.Where(e => e.channel != 1 || !hide_ids.Contains(e.accountId));
+            return new APIResult(new { data = result });
+        }
+
+
+
+    }
+}

+ 1 - 1
molilian.api/Controllers/admin/TaobaoController.cs

@@ -182,7 +182,7 @@ namespace molilian.api.Controllers
                 orderBy = sort switch
                 {
                     //"num" => $"num {order}",
-                    _ => $"{sort} {order}",
+                    _ => $"{sort} {order},ID DESC",
                 };
             }
 

+ 3 - 1
molilian.api/Controllers/public/TaskController.cs

@@ -698,7 +698,9 @@ namespace molilian.api.Controllers
                 {
                     if (!account.status) continue;
 #if DEBUG
-                    if (account.id != 10) continue;
+                    startDate = DateTime.Parse("2024-07-31");
+                    endDate = DateTime.Parse("2024-07-31");
+                    if (account.id != 15) continue;
 #endif
                     if (account.is_hide) continue;
 

+ 37 - 0
molilian.api/Controllers/public/TestController.cs

@@ -28,6 +28,43 @@ namespace molilian.api.Controllers
             _accessor = accessor;
         }
 
+        [HttpGet]
+        public async Task<ActionResult> ReleaseEipAddress(string allocationId)
+        {
+            AliyunCore core = new AliyunCore(6);
+            var success = core.ReleaseEipAddress("cn-beijing", allocationId);
+            return new APIResult(new { success });
+        }
+
+
+        [HttpGet]
+        public async Task<ActionResult> CreateNetworkInterface(string ecsid)
+        {
+            AliyunCore core = new AliyunCore(6);
+            //创建弹性网卡并绑定公网IP
+            var success = core.EcsCreateNetworkInterface("cn-beijing", ecsid);
+
+            return new APIResult(new { success });
+        }
+
+
+        [HttpGet]
+        public async Task<ActionResult> EcsAssignPrivateIpAddresses(string ecsid, int count)
+        {
+            AliyunCore core = new AliyunCore(6);
+            //创建弹性网卡并绑定公网IP
+            var success = core.EcsAssignPrivateIpAddresses("cn-beijing", ecsid, count);
+            return new APIResult(new { success });
+        }
+
+        [HttpGet]
+        public async Task<ActionResult> QueryAccountBalance()
+        {
+            AliyunPlus plus = new AliyunPlus("LTAI5tQbkTjtULQcrWGaw2VJ", "UIkkolVVEddooOKOIUByCqymZkK6ZA");
+            var response = plus.QueryAccountBalance();
+            var balance = response.Body.Data.AvailableAmount;
+            return new APIResult(new { response });
+        }
 
         //[HttpGet]
         //public async Task<ActionResult> test(string table = "tk_parse_logs_shop", int count = 100)

+ 6 - 3
molilian.api/Controllers/public/TkController.cs

@@ -47,6 +47,7 @@ namespace molilian.api.Controllers
             var channel = form.Read("c", string.Empty);
             var ip = form.Read("ip", string.Empty);
             var oaid = form.Read("oaid", string.Empty);
+            var commerceType = form.Read<int>("commerceType", 0);
 
 
             //验证签名
@@ -71,7 +72,7 @@ namespace molilian.api.Controllers
             {
                 return new APIResult(new { success = false, message = "验证错误4" }, APIResultCodeEnum.Unauthorized);
             }
-            return await UnionParseCore.UnionParseAsync(content, channel, ip, oaid);
+            return await UnionParseCore.UnionParseAsync(content, channel, commerceType, ip, oaid);
         }
 
         [HttpPost]
@@ -82,11 +83,13 @@ namespace molilian.api.Controllers
             var ip = form.Read("ip", string.Empty);
             var oaid = form.Read("oaid", string.Empty);
             int accountid = form.Read("aid", 0);
+            var commerceType = form.Read<int>("commerceType", 0);
+
 #if DEBUG
             //ip = "127.0.0.1";
             //oaid = "test-oaid";
 #endif
-            return await UnionParseCore.UnionParseAsync(content, channel, ip, oaid, accountid);
+            return await UnionParseCore.UnionParseAsync(content, channel, commerceType, ip, oaid, accountid);
         }
 
         [HttpPost]
@@ -222,7 +225,7 @@ namespace molilian.api.Controllers
                     });
 
                 }
-                result = await alimama.UnionParseAsync(content, result);
+                result = await alimama.UnionParseAsync(content, 0, result);
             }
             catch (Exception ex)
             {

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 0 - 0
molilian.api/Properties/PublishProfiles/https___ccr.ccs.tencentyun.com_shaobin.pubxml.user


+ 32 - 0
molilian.core/Core/aliyun/AliyunAccountDTO.cs

@@ -0,0 +1,32 @@
+
+using dodohold.core;
+
+namespace molilian.core
+{
+    public partial class AliyunAccountDTO
+    {
+
+        [Key]
+        public int Id { get; set; }
+        public string name { get; set; } = string.Empty;
+        public string username { get; set; } = string.Empty;
+        public string password { get; set; } = string.Empty;
+        public string company { get; set; } = string.Empty;
+        public string description { get; set; } = string.Empty;
+        public string mobile { get; set; } = string.Empty;
+        public string accessKeyId { get; set; } = string.Empty;
+        public string accessKeySecret { get; set; } = string.Empty;
+        public bool status { get; set; } = false;
+        public DateTime create_time { get; set; } = DateTime.MinValue;
+
+        public DateTime last_time { get; set; } = DateTime.MinValue;
+        public decimal balance { get; set; } = 0;
+        public string regions { get; set; } = string.Empty;
+
+
+
+    }
+
+
+}
+

+ 163 - 0
molilian.core/Core/aliyun/AliyunCore.cs

@@ -0,0 +1,163 @@
+using dodohold.core;
+using Dataoke;
+using Tea;
+using AlibabaCloud.SDK.BssOpenApi20171214.Models;
+using AlibabaCloud.SDK.Ecs20140526.Models;
+using AlibabaCloud.SDK.Vpc20160428.Models;
+using TencentCloud.Dbbrain.V20210527.Models;
+using Org.BouncyCastle.Bcpg.OpenPgp;
+using TencentCloud.Tke.V20180525.Models;
+
+namespace molilian.core
+{
+
+    public partial class AliyunCore
+    {
+        private AliyunPlus plus;
+        private AliyunAccountDTO _account;
+
+        public AliyunCore(int id)
+        {
+            _account = new DBContext.Table("aliyun_pool").Get<AliyunAccountDTO>(id);
+            if (_account == null) throw new Exception("无效账号");
+            plus = new AliyunPlus(_account.accessKeyId, _account.accessKeySecret);
+        }
+
+        public bool EcsCreateNetworkInterface(string region, string instanceId)
+        {
+            try
+            {
+                //查询实例信息
+                var instance = plus.DescribeInstanceAttribute(region, instanceId);
+                var vswitchId = instance.Body.VpcAttributes.VSwitchId;
+                var securityGroupId = instance.Body.SecurityGroupIds.SecurityGroupId;
+
+                //申请弹性网卡
+                var response = plus.CreateNetworkInterface(region, vswitchId, securityGroupId);
+                string networkInterfaceId = response.Body.NetworkInterfaceId;
+                string privateIpAddress = response.Body.PrivateIpAddress;
+                if (string.IsNullOrEmpty(networkInterfaceId)) throw new Exception(response.Body.ToString());
+
+                //绑定网卡
+                plus.AttachNetworkInterface(region, instanceId, networkInterfaceId);
+
+                //申请并绑定公网IP
+                EcsAssociateEipAddress(region, networkInterfaceId, privateIpAddress);
+                return true;
+            }
+            catch (Exception ex)
+            {
+                throw new Exception(ex.Message);
+            }
+        }
+
+        public bool EcsAssignPrivateIpAddresses(string region, string instanceId, int count)
+        {
+            try
+            {
+                //查询实例信息
+                var instance = plus.DescribeInstanceAttribute(region, instanceId);
+                var vswitchId = instance.Body.VpcAttributes.VSwitchId;
+                var securityGroupId = instance.Body.SecurityGroupIds.SecurityGroupId;
+
+                var response = plus.DescribeNetworkInterfaces(region, instanceId);
+                foreach (var e in response.Body.NetworkInterfaceSets.NetworkInterfaceSet)
+                {
+                    if ("Secondary".Equals(e.Type))
+                    {
+#if DEBUG
+                        var response2 = plus.DescribeNetworkInterfaceAttribute(region, e.NetworkInterfaceId);
+                        var PrivateIpAddressList = response2.Body.PrivateIpSets.PrivateIpSet;
+
+                        foreach (var privateIp in PrivateIpAddressList)
+                        {
+                            if (privateIp.Primary == true) continue;
+                            var privateIpAddress = privateIp.PrivateIpAddress;
+
+                            //申请公网ip
+                            var eip = plus.AllocateEipAddress(region);
+                            var allocationId = eip.Body.AllocationId;
+                            string eipAddress = eip.Body.EipAddress;
+
+                            //绑定公网ip
+                            var AssociateEipAddress =
+                                plus.AssociateEipAddress(
+                                    region, allocationId, e.NetworkInterfaceId, EIPInstanceType.NetworkInterface, privateIpAddress);
+                        }
+
+#else
+                        //添加辅助私网
+                        var response2 = plus.AssignPrivateIpAddresses(region, e.NetworkInterfaceId, count);
+                        var PrivateIpAddressList = response2.Body.AssignedPrivateIpAddressesSet.PrivateIpSet.PrivateIpAddress;
+                        
+                        foreach (var privateIpAddress in PrivateIpAddressList)
+                        {
+                            //申请公网ip
+                            var eip = plus.AllocateEipAddress(region);
+                            var allocationId = eip.Body.AllocationId;
+                            string eipAddress = eip.Body.EipAddress;
+
+                            //绑定公网ip
+                            var AssociateEipAddress =
+                                plus.AssociateEipAddress(region, allocationId, e.NetworkInterfaceId, EIPInstanceType.NetworkInterface, privateIpAddress);
+                        }
+
+#endif
+                         
+                        return true;
+                    }
+                }
+
+                return false;
+            }
+            catch (Exception ex)
+            {
+                throw new Exception(ex.Message);
+            }
+        }
+
+        /// <summary>
+        /// 申请并绑定公网IP
+        /// </summary>
+        /// <param name="region"></param>
+        /// <param name="instanceId"></param>
+        /// <param name="privateIpAddress"></param>
+        /// <returns></returns>
+        /// <exception cref="Exception"></exception>
+        public bool EcsAssociateEipAddress(string region, string networkInterfaceId, string privateIpAddress)
+        {
+            try
+            {
+                //申请公网ip
+                var eip = plus.AllocateEipAddress(region);
+                var allocationId = eip.Body.AllocationId;
+                string eipAddress = eip.Body.EipAddress;
+
+                //绑定公网ip
+                var AssociateEipAddress =
+                    plus.AssociateEipAddress(region, allocationId, networkInterfaceId, EIPInstanceType.NetworkInterface);
+                return true;
+            }
+            catch (Exception ex)
+            {
+                throw new Exception(ex.Message);
+            }
+        }
+        public bool ReleaseEipAddress(string region, string allocationId)
+        {
+            try
+            {
+                plus.ReleaseEipAddress(region, allocationId);
+                return true;
+            }
+            catch (Exception ex)
+            {
+                throw new Exception(ex.Message);
+            }
+        }
+
+    }
+
+
+}
+

+ 77 - 16
molilian.core/Core/taoke/UnionParseCore.cs

@@ -31,18 +31,19 @@ namespace molilian.core
 {
     public partial class UnionParseCore
     {
-        public static async Task<ActionResult> UnionParseAsync(string content, string channel, string ip, string oaid, int accountid = 0)
+        public static async Task<ActionResult> UnionParseAsync(string content, string channel, int commerceType, string ip, string oaid, int accountid = 0)
         {
+
             content = content.Trim();
             return channel switch
             {
                 "wemeet" => await WemeetParseAsync(content, ip, oaid),
                 "bdpan" => PanParse(content, ip, oaid),
-                "jd" => await JdParseAsync(content, ip, oaid, accountid),
-                "ks" => await KsParseAsync(content, ip, oaid, accountid),
-                "dy" => await DyParseAsync(content, ip, oaid),
-                "pdd" => await PddParseAsync(content, ip, oaid, accountid),
-                "tb" => await TaobaoParseAsync(content, ip, oaid, accountid),
+                "jd" => await JdParseAsync(content, commerceType, ip, oaid, accountid),
+                "ks" => await KsParseAsync(content, commerceType, ip, oaid, accountid),
+                "dy" => await DyParseAsync(content, commerceType, ip, oaid),
+                "pdd" => await PddParseAsync(content, commerceType, ip, oaid, accountid),
+                "tb" => await TaobaoParseAsync(content, commerceType, ip, oaid, accountid),
                 _ => await DeeplinkParseCore.ParseAsync(content, channel, ip, oaid),
             };
         }
@@ -142,10 +143,11 @@ namespace molilian.core
             return new APIResult(info, code);
         }
 
-        public static async Task<APIResult> TaobaoParseAsync(string content,
+        public static async Task<APIResult> TaobaoParseAsync(string content, int commerceType,
             string ip = "", string oaid = "",
             int accountid = 0)
         {
+            bool other_aff = false;
             AlimamaPlus alimama = null;
             //content = content.UrlDecode();
             content = content[..Math.Min(1000, content.Length)];
@@ -194,9 +196,11 @@ namespace molilian.core
                     return TaobaoParseOutput(result, swData, new
                     {
                         result.success,
+                        result.commercial,
                         result.message,
                         result.content,
                         result.itemName,
+                        other_aff,
                         result.deeplink_url,
                     });
                 }
@@ -218,9 +222,11 @@ namespace molilian.core
                     return TaobaoParseOutput(result, swData, new
                     {
                         result.success,
+                        result.commercial,
                         result.message,
                         result.content,
                         result.itemName,
+                        other_aff,
                         result.deeplink_url,
                     });
                 }
@@ -228,6 +234,41 @@ namespace molilian.core
                 //============================== 放弃转链-初步筛选2 ==============================
                 bool is_aff_link = false;
                 if (!string.IsNullOrEmpty(result.shortLinkurl)) is_aff_link = AlimamaPlus.IsAffLink(result.shortLinkurl);
+                if (!is_tao_url && is_tao_token)
+                {
+                    //淘宝口令
+                    result.success = false;
+                    result.message = "放弃转链";
+                    result.reason = "初步筛选2";
+                    result.subCode = TkSubCodeEnum.Prelim2;
+                    result.itemName = "点击打开淘宝APP";
+                    _ = TkLogCore.ParseLogAsync(result);
+
+
+                    //20241108 特例
+                    string ruleKey = $"tmp_rules:{DateTime.Now:yyyyMMdd}";
+                    var count = RedisHelper.IncrBy(ruleKey);
+                    if (DateTime.Now < DateTime.Parse("2024-11-11") && count < 2500)
+                    {
+                        //"https://s.click.taobao.com/t?union_lens=lensId%3APUB%401730991020%400bbb0a39_0e75_193071ad936_c566%4001%40eyJmbG9vcklkIjozODg1Miiwiic3BtQiiI6Il9wb3J0YWxfdjJfcGFnZXNfYWN0aXZpdHlfb2ZmaWNpYWxfaW5kZXhfaHRtIn0ie%3BeventPageId%3A20150318020007201&e=m%3D2%26s%3DipuVKjYImbNw4vFB6t2Z2iperVdZeJviU%2F9%2F0taeK29yINtkUhsv0KWvzu%2FHMi3%2BFPhC4MirEWStw6LBB4w3HYXT%2BqQ2P5OIQVNSryTmvs7YddWYbxmvGTMNfihJN%2FGnAGIx0oe2X2hZfJ7ZQxC1%2FU3rpAhWgptfEBnEBk3xaGylLmcSHKfaX1CIFRJhZoJ2keMqUwSQcLRC0TzsMy8kp7Hfv3%2BBYcPW3eHn14rW1PB5SunYCHQHRbw6LwQYf%2F1JuyhJem%2BM5OoR2cbDLktPLiIOenYkFIXa2HzNl%2Bm1VXoil%2F2L3b1aA6a%2FoVHlY%2BqZ2kyLuBX5NHCAQVYCmAmuozC39JfnbJNrE%2FSR3F9BSjOYe76q6w0hyfybhwAASyyp5XMWEyz25ulHMwkL2n%2F7nNBiFmadXyjFDPu12TgSnbZtfjDbrVTLHb6MowVEq7z9LgOFRSuRLesvlLykGd2CaRk8ezhE61zXa8yR1eex6ip3KqbOh7CEmgCLaFxcnT%2BrGuviRFaBil8Mlu5kMKse3g%3D%3D";
+
+                        string hb_url = "https://s.click.taobao.com/t?union_lens=lensId%3APUB%401730991060%400b510772_0df6_193071b768d_210f%4001%40eyJmbG9vcklkIjozODg1Miiwiic3BtQiiI6Il9wb3J0YWxfdjJfcGFnZXNfYWN0aXZpdHlfb2ZmaWNpYWxfaW5kZXhfaHRtIn0ie%3BeventPageId%3A20150318020016843&e=m%3D2%26s%3DA1AHKD9F7Nhw4vFB6t2Z2iperVdZeJviU%2F9%2F0taeK29yINtkUhsv0KWvzu%2FHMi3%2Bh1wntvOGDCytw6LBB4w3HYXT%2BqQ2P5OIQVNSryTmvs7eznT8c0%2BOxucX6%2FIvhSD5AGIx0oe2X2hZfJ7ZQxC1%2FU3rpAhWgptfEBnEBk3xaGylLmcSHKfaX1CIFRJhZoJ2keMqUwSQcLRC0TzsMy8kp7Hfv3%2BBYcPW3eHn14rW1PB5SunYCHQHRbw6LwQYf%2F1JuyhJem%2BM5OoR2cbDLktPLiIOenYkFIXaB%2FWmSjJ%2FDetdnBNxJusisiH18dRGjHzjUh%2Bx4%2Bh6gbwLqirZAkaxvnIKgJtaeeuKsJkGnmNeMxV2b5AccURU%2FXqss%2B9QPoF86hteE8NJKpolfPKodRMJmRfFCEuMVaVFTjJ9EustsCzTbaXzU0HzGQ3G0oSVAhvq8dJ646N9%2BfPG7KP%2FW7aJTlBg0B0VOPmAfTYWTuIBgHgsBQ1POZZlkf%2BtQEx4g%2BcAxnAryvg3Dknnic12Z1shopsQ%2FFWmC5aPxgxdTc00KD8%3D";
+                        result.deeplink_url = AlimamaPlus.GetDeeplink(hb_url);
+                        RedisHelper.Expire(ruleKey, 86400 * 10);
+                    }
+                    other_aff = true;
+                    return TaobaoParseOutput(result, swData, new
+                    {
+                        result.success,
+                        result.commercial,
+                        result.message,
+                        result.content,
+                        result.itemName,
+                        other_aff,
+                        result.deeplink_url,
+                    });
+
+                }
                 if ((!is_tao_url && is_tao_token) || is_aff_link)
                 {
                     //没有短链接都放弃
@@ -238,12 +279,15 @@ namespace molilian.core
                     result.itemName = "点击打开淘宝APP";
                     _ = TkLogCore.ParseLogAsync(result);
 
+                    other_aff = true;
                     return TaobaoParseOutput(result, swData, new
                     {
                         result.success,
+                        result.commercial,
                         result.message,
                         result.content,
                         result.itemName,
+                        other_aff,
                         result.deeplink_url,
                     });
                 }
@@ -265,9 +309,11 @@ namespace molilian.core
                     return TaobaoParseOutput(result, swData, new
                     {
                         result.success,
+                        result.commercial,
                         result.message,
                         result.content,
                         result.itemName,
+                        other_aff,
                         result.deeplink_url,
                     });
 
@@ -286,9 +332,11 @@ namespace molilian.core
                     return TaobaoParseOutput(result, swData, new
                     {
                         result.success,
+                        result.commercial,
                         result.message,
                         result.content,
                         result.itemName,
+                        other_aff,
                         result.deeplink_url,
                     });
                 }
@@ -308,11 +356,13 @@ namespace molilian.core
                     return TaobaoParseOutput(result, swData, new
                     {
                         result.success,
+                        result.commercial,
                         result.message,
                         result.content,
                         result.couponAmount,
                         result.taoToken,
                         result.shortLinkurl,
+                        other_aff,
                         result.deeplink_url,
                     });
                 }
@@ -329,7 +379,7 @@ namespace molilian.core
                 using var cts = new CancellationTokenSource();
                 cts.CancelAfter(timeout);
 
-                var requestTask = Task.Run(() => alimama.UnionParse2Async(content, result, cts.Token, swData), cts.Token);
+                var requestTask = Task.Run(() => alimama.UnionParse2Async(content, commerceType, result, cts.Token, swData), cts.Token);
                 var delayTask = Task.Delay(timeout, cts.Token);
                 var completedTask = await Task.WhenAny(requestTask, delayTask);
                 if (completedTask == requestTask)
@@ -384,9 +434,19 @@ namespace molilian.core
             }
             _ = TkLogCore.ParseLogAsync(result, alimama);
 
+            switch (result.reason)
+            {
+                case "其他推广链接":
+                //case "排除淘口令":
+                case "纯口令 没链接":
+                    other_aff = true;
+                    break;
+            }
+
             return TaobaoParseOutput(result, swData, new
             {
                 result.success,
+                result.commercial,
                 result.message,
                 link_type = result.link_type.ToString(),
                 channel = result?.channel.ToString(),
@@ -402,6 +462,7 @@ namespace molilian.core
                 result.deeplink_url,
                 result.content,
                 result.taoToken,
+                other_aff,
             });
         }
 
@@ -421,7 +482,7 @@ namespace molilian.core
             }, code);
         }
 
-        public static async Task<APIResult> JdParseAsync(string content, string ip, string oaid,
+        public static async Task<APIResult> JdParseAsync(string content, int commerceType, string ip, string oaid,
             int accountid = 0, CancellationToken cancellationToken = default)
         {
             var result = JdUnionPlus.GetFormattedObject(content, ip, oaid);
@@ -510,7 +571,7 @@ namespace molilian.core
 
                 var plus = new JdUnionPlus(account);
 
-                result = await plus.JdParseAsync(content, result, cancellationToken);
+                result = await plus.JdParseAsync(content, commerceType, result, cancellationToken);
             }
             catch (Exception ex)
             {
@@ -549,7 +610,7 @@ namespace molilian.core
 
         }
 
-        public static async Task<APIResult> DyParseAsync(string content, string ip, string oaid, CancellationToken cancellationToken = default)
+        public static async Task<APIResult> DyParseAsync(string content, int commerceType, string ip, string oaid, CancellationToken cancellationToken = default)
         {
             var result = DyUnionPlus.GetFormattedObject(content, ip, oaid);
             content = content.UrlDecode();
@@ -586,7 +647,7 @@ namespace molilian.core
                     _ = TkLogCore.ParseLogAsync(result);
                     return new APIResult(result);
                 }
-                result = await DyUnionPlus.DyParseAsync(account, content, result, cancellationToken);
+                result = await DyUnionPlus.DyParseAsync(account, content, commerceType, result, cancellationToken);
             }
             catch (Exception ex)
             {
@@ -631,7 +692,7 @@ namespace molilian.core
             }, IfExceptional ? APIResultCodeEnum.NotAcceptable : APIResultCodeEnum.OK);
         }
 
-        public static async Task<APIResult> PddParseAsync(string content, string ip, string oaid,
+        public static async Task<APIResult> PddParseAsync(string content, int commerceType, string ip, string oaid,
             int accountid = 0, CancellationToken cancellationToken = default)
         {
             var result = PddUnionPlus.GetFormattedObject(content, ip, oaid);
@@ -687,7 +748,7 @@ namespace molilian.core
 
                 var plus = new PddUnionPlus(account);
 
-                result = await plus.PddParseAsync(content, result, cancellationToken);
+                result = await plus.PddParseAsync(content, commerceType, result, cancellationToken);
             }
             catch (Exception ex)
             {
@@ -738,7 +799,7 @@ namespace molilian.core
 
 
 
-        public static async Task<APIResult> KsParseAsync(string content, string ip, string oaid,
+        public static async Task<APIResult> KsParseAsync(string content, int commerceType, string ip, string oaid,
             int accountid = 0, CancellationToken cancellationToken = default)
         {
             var result = KsUnionPlus.GetFormattedObject(content, ip, oaid);
@@ -797,7 +858,7 @@ namespace molilian.core
 
                 var plus = new KsUnionPlus(account);
 
-                result = await plus.KsParseAsync(content, result, cancellationToken);
+                result = await plus.KsParseAsync(content, commerceType, result, cancellationToken);
             }
             catch (Exception ex)
             {

+ 178 - 84
molilian.core/Core/tool/DeeplinkParseCore.cs

@@ -5,10 +5,12 @@ using Microsoft.AspNetCore.Mvc;
 using Microsoft.Extensions.FileSystemGlobbing.Internal;
 using Sayaka.Common;
 using Spire.Pdf.Annotations;
+using Spire.Pdf.Exporting.XPS.Schema;
 using System.Security.Cryptography;
 using System.Text.RegularExpressions;
 using System.Web;
 using System.Xml.Linq;
+using TencentCloud.Tcss.V20201101.Models;
 namespace molilian.core
 {
     public partial class DeeplinkParseCore
@@ -221,13 +223,27 @@ namespace molilian.core
                 if (match.Success)
                 {
 
+                    if (rule.resources.Count > 0)
+                    {
+                        foreach (var resource in rule.resources)
+                        {
+                            Dictionary<string, string> resResult = await ResourceProcessing(match, resource);
+                            foreach (var e in resResult)
+                            {
+                                if (deeplink.Contains(e.Key))
+                                {
+                                    deeplink = deeplink.Replace(e.Key, e.Value);
+                                }
+                            }
+                        }
+                    }
+
                     if (match.Groups.Count > 1)
                     {
+
                         for (var i = 1; i < match.Groups.Count; i++)
                         {
                             string val = match.Groups[i].Value;
-
-
                             switch (rule.plugin)
                             {
                                 case "redu":
@@ -242,90 +258,10 @@ namespace molilian.core
                                     }
                                     break;
                             }
-
-                            if (deeplink.Contains("{url:"))
-                            {
-                                string encodedUrl = HttpUtility.UrlEncode(val);
-                                deeplink = deeplink.Replace($"{{url:{i - 1}}}", encodedUrl);
-                                //deeplink = deeplink.Replace($"{{url:{i - 1}}}", val.UrlEncode());
-                            }
-                            if (prompt_text.Contains("{url:"))
-                            {
-                                string encodedUrl = HttpUtility.UrlEncode(val);
-                                prompt_text = prompt_text.Replace($"{{url:{i - 1}}}", encodedUrl);
-                                //prompt_text = prompt_text.Replace($"{{url:{i - 1}}}", val.UrlEncode());
-                            }
-
-                            if (deeplink.Contains("{decode:"))
-                            {
-                                string encodedUrl = HttpUtility.UrlDecode(val);
-                                deeplink = deeplink.Replace($"{{decode:{i - 1}}}", encodedUrl);
-                                //deeplink = deeplink.Replace($"{{url:{i - 1}}}", val.UrlEncode());
-                            }
-                            if (prompt_text.Contains("{decode:"))
-                            {
-                                string encodedUrl = HttpUtility.UrlDecode(val);
-                                prompt_text = prompt_text.Replace($"{{decode:{i - 1}}}", encodedUrl);
-                            }
-
-                            //两次url编码
-                            if (deeplink.Contains("{url2:"))
-                            {
-                                string encodedUrl = HttpUtility.UrlEncode(val);
-                                encodedUrl = HttpUtility.UrlEncode(encodedUrl);
-                                deeplink = deeplink.Replace($"{{url2:{i - 1}}}", encodedUrl);
-                            }
-                            if (prompt_text.Contains("{url2:"))
-                            {
-                                string encodedUrl = HttpUtility.UrlEncode(val);
-                                encodedUrl = HttpUtility.UrlEncode(encodedUrl);
-                                prompt_text = prompt_text.Replace($"{{url2:{i - 1}}}", encodedUrl);
-                            }
-
-
-                            //三次url解码
-                            if (deeplink.Contains("{url3:"))
-                            {
-                                string encodedUrl = HttpUtility.UrlEncode(val);
-                                encodedUrl = HttpUtility.UrlEncode(encodedUrl);
-                                deeplink = deeplink.Replace($"{{url3:{i - 1}}}", encodedUrl);
-                            }
-                            if (prompt_text.Contains("{url3:"))
-                            {
-                                string encodedUrl = HttpUtility.UrlEncode(val);
-                                encodedUrl = HttpUtility.UrlEncode(encodedUrl);
-                                prompt_text = prompt_text.Replace($"{{url3:{i - 1}}}", encodedUrl);
-                            }
-
-                            //atob
-                            if (deeplink.Contains("{atob:"))
-                            {
-                                string encodedUrl = HttpUtility.UrlDecode(val);
-                                deeplink = deeplink.Replace($"{{atob:{i - 1}}}", encodedUrl.FromBase64());
-                            }
-                            if (prompt_text.Contains("{atob:"))
-                            {
-                                string encodedUrl = HttpUtility.UrlDecode(val);
-                                prompt_text = prompt_text.Replace($"{{atob:{i - 1}}}", encodedUrl.FromBase64());
-                            }
-
-                            //btoa
-                            if (deeplink.Contains("{btoa:"))
-                            {
-                                string encodedUrl = HttpUtility.UrlEncode(val);
-                                deeplink = deeplink.Replace($"{{btoa:{i - 1}}}", val.ToBase64());
-                            }
-                            if (prompt_text.Contains("{btoa:"))
-                            {
-                                string encodedUrl = HttpUtility.UrlEncode(val);
-                                prompt_text = prompt_text.Replace($"{{btoa:{i - 1}}}", val.ToBase64());
-                            }
-
-
-                            deeplink = deeplink.Replace($"{{{i - 1}}}", val);
-                            prompt_text = prompt_text.Replace($"{{{i - 1}}}", val);
+                            ReplaceProcessing(val, i, ref deeplink, ref prompt_text);
                         }
 
+
                         deeplink = Regex.Replace(deeplink, @"\{\d+\}", string.Empty);
                         prompt_text = Regex.Replace(prompt_text, @"\{\d+\}", string.Empty);
 
@@ -353,7 +289,165 @@ namespace molilian.core
             }
 
             return null;
+        }
+
+        /// <summary>
+        /// 占位符的处理
+        /// </summary>
+        /// <param name="word"></param>
+        /// <param name="i"></param>
+        /// <param name="deeplink"></param>
+        /// <param name="prompt_text"></param>
+        private static void ReplaceProcessing(string word, int i, ref string deeplink, ref string prompt_text)
+        {
+            if (deeplink.Contains("{url:"))
+            {
+                string encodedUrl = HttpUtility.UrlEncode(word);
+                deeplink = deeplink.Replace($"{{url:{i - 1}}}", encodedUrl);
+            }
+            if (prompt_text.Contains("{url:"))
+            {
+                string encodedUrl = HttpUtility.UrlEncode(word);
+                prompt_text = prompt_text.Replace($"{{url:{i - 1}}}", encodedUrl);
+            }
+
+            if (deeplink.Contains("{decode:"))
+            {
+                string encodedUrl = HttpUtility.UrlDecode(word);
+                deeplink = deeplink.Replace($"{{decode:{i - 1}}}", encodedUrl);
+            }
+            if (prompt_text.Contains("{decode:"))
+            {
+                string encodedUrl = HttpUtility.UrlDecode(word);
+                prompt_text = prompt_text.Replace($"{{decode:{i - 1}}}", encodedUrl);
+            }
+
+            //两次url编码
+            if (deeplink.Contains("{url2:"))
+            {
+                string encodedUrl = HttpUtility.UrlEncode(word);
+                encodedUrl = HttpUtility.UrlEncode(encodedUrl);
+                deeplink = deeplink.Replace($"{{url2:{i - 1}}}", encodedUrl);
+            }
+            if (prompt_text.Contains("{url2:"))
+            {
+                string encodedUrl = HttpUtility.UrlEncode(word);
+                encodedUrl = HttpUtility.UrlEncode(encodedUrl);
+                prompt_text = prompt_text.Replace($"{{url2:{i - 1}}}", encodedUrl);
+            }
+
+
+            //三次url解码
+            if (deeplink.Contains("{url3:"))
+            {
+                string encodedUrl = HttpUtility.UrlEncode(word);
+                encodedUrl = HttpUtility.UrlEncode(encodedUrl);
+                deeplink = deeplink.Replace($"{{url3:{i - 1}}}", encodedUrl);
+            }
+            if (prompt_text.Contains("{url3:"))
+            {
+                string encodedUrl = HttpUtility.UrlEncode(word);
+                encodedUrl = HttpUtility.UrlEncode(encodedUrl);
+                prompt_text = prompt_text.Replace($"{{url3:{i - 1}}}", encodedUrl);
+            }
+
+            //atob
+            if (deeplink.Contains("{atob:"))
+            {
+                string encodedUrl = HttpUtility.UrlDecode(word);
+                deeplink = deeplink.Replace($"{{atob:{i - 1}}}", encodedUrl.FromBase64());
+            }
+            if (prompt_text.Contains("{atob:"))
+            {
+                string encodedUrl = HttpUtility.UrlDecode(word);
+                prompt_text = prompt_text.Replace($"{{atob:{i - 1}}}", encodedUrl.FromBase64());
+            }
+
+            //btoa
+            if (deeplink.Contains("{btoa:"))
+            {
+                string encodedUrl = HttpUtility.UrlEncode(word);
+                deeplink = deeplink.Replace($"{{btoa:{i - 1}}}", word.ToBase64());
+            }
+            if (prompt_text.Contains("{btoa:"))
+            {
+                string encodedUrl = HttpUtility.UrlEncode(word);
+                prompt_text = prompt_text.Replace($"{{btoa:{i - 1}}}", word.ToBase64());
+            }
+            deeplink = deeplink.Replace($"{{{i - 1}}}", word);
+            prompt_text = prompt_text.Replace($"{{{i - 1}}}", word);
+        }
+
+        private static async Task<Dictionary<string, string>> ResourceProcessing(Match baseMatch, DeeplinkResources resource)
+        {
+            Dictionary<string, string> result = new Dictionary<string, string>();
+            string url = resource.url_pattern;
+            string prompt_text = string.Empty;
+            for (var i = 1; i < baseMatch.Groups.Count; i++)
+            {
+                string val = baseMatch.Groups[i].Value;
+                ReplaceProcessing(val, i, ref url, ref prompt_text);
+            }
+
+            string content = string.Empty;
+            try
+            {
+                switch (resource.url_action)
+                {
+                    case UrlAction.Redirect:
+                        {
+                            var response = await new WebClientUtility
+                            {
+                                Proxy = ProxyNodesCore.RandomOne(),
+                                UserAgent = ProviderFakeUserAgent.RandomMobile,
+                                AllowAutoRedirect = false
+                            }.RequestAsync(url);
+                            if (response.ResponseMessage != null)
+                            {
+                                content = response.ResponseMessage.Headers.Location.ToString();
+                                content = content.UrlDecode();
+                            }
+                        }
+                        break;
+                    case UrlAction.Body:
+                        {
+                            var response = await new WebClientUtility
+                            {
+                                Proxy = ProxyNodesCore.RandomOne(),
+                                UserAgent = ProviderFakeUserAgent.RandomMobile,
+                                AllowAutoRedirect = true
+                            }.RequestAsync(url);
+                            content = response.Body();
+                        }
+                        break;
+                    case UrlAction.None:
+                        //{
+                        //    content = url;
+                        //}
+                        break;
+                }
+            }
+            catch (Exception ex)
+            {
+                //Console.WriteLine($"{url}\t{rule.url_action}\t{ex.Message}");
+            }
+
+            if (string.IsNullOrEmpty(content)) { return result; }
 
+            for (int i = 0; i < resource.pattern.Count; i++)
+            {
+                string val = string.Empty;
+                var regex = new Regex(resource.pattern[i]);
+                var match = regex.Match(content);
+                if (match.Success)
+                {
+                    val = match.Groups[1].Value;
+                }
+
+                string key = $"{{{i}@{resource.name}}}";
+                result.Add(key, val);
+            }
+            return result;
         }
 
         public static async Task<string> PluginDyParseAsync(string content, string matchText, DeeplinkParseDataDTO deeplinkResult, CancellationToken cancellationToken = default)

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

@@ -49,6 +49,11 @@ namespace molilian.core
         /// </summary>
         Other = 109,
 
+        /// <summary>
+        /// 产商放弃
+        /// </summary>
+        PartnersDrop = 110,
+
         /// <summary>
         /// 初筛1.5
         /// </summary>
@@ -74,6 +79,7 @@ namespace molilian.core
         public int accountId { get; set; } = 0;
         public string accountName { get; set; } = string.Empty;
         public bool success { get; set; } = true;
+        public bool commercial { get; set; } = false;
         public string message { get; set; } = string.Empty;
         public string reason { get; set; } = string.Empty;
         public string content { get; set; } = string.Empty;

+ 15 - 1
molilian.core/DTO/deeplink/DeeplinkParseRuleDTO.cs

@@ -1,4 +1,5 @@
 using dodohold.core;
+using Spire.Pdf.Exporting.XPS.Schema;
 
 namespace molilian.core
 {
@@ -6,7 +7,7 @@ namespace molilian.core
     {
         None = 0,
         Redirect = 1,
-        Body = 2
+        Body = 2,
     }
 
     public class DeeplinkParseRule
@@ -20,8 +21,21 @@ namespace molilian.core
         public string prompt_text { get; set; } = string.Empty;
         public bool enable { get; set; } = true;
         public List<DeeplinkParseRule> childs { get; set; } = new();
+        public List<DeeplinkResources> resources { get; set; } = new();
     }
 
+
+    public class DeeplinkResources
+    {
+        public string name { get; set; } = string.Empty;
+        public string url_pattern { get; set; } = string.Empty;
+        public UrlAction url_action { get; set; } = UrlAction.None;
+        public List<string> pattern { get; set; } = [];
+        public bool enable { get; set; } = true;
+    }
+
+
+
     [Table("deeplink_parse_rule")]
     public class DeeplinkParseRuleDTO
     {

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

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

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

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

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

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

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

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

+ 7 - 0
molilian.core/Plus/Alimama/crawler.cs

@@ -530,12 +530,19 @@ namespace molilian.core
                 var root = body.Convert2JsonElement();
 
                 int resultCode = root.Read<int>("resultCode", 0);
+                var bizErrorDesc = root.Read("bizErrorDesc", string.Empty);
                 bool success = root.Read("success", false);
                 if (!success)
                 {
                     _ = new LoggerLibrary("report", "error")
                         .Info(url, body)
                         .SaveAsync();
+
+                    if (resultCode == 500 && bizErrorDesc.Contains("For input string"))
+                    {
+                        return;
+                    }
+                    //{"success":false,"resultCode":500,"bizErrorDesc":"For input string: \"null\"","bizErrorCode":400}
                     throw new Exception(body);
                 }
 

+ 30 - 1
molilian.core/Plus/Alimama/parse.cs

@@ -99,7 +99,7 @@ namespace molilian.core
             return result;
         }
 
-        public async Task<TkDataDTO> UnionParseAsync(string content, TkDataDTO result,
+        public async Task<TkDataDTO> UnionParseAsync(string content, int commerceType, TkDataDTO result,
             CancellationToken cancellationToken = default,
             Dictionary<string, long> swData = null)
         {
@@ -120,6 +120,22 @@ namespace molilian.core
                 result.content = content;
                 //result.deeplink_url = GetDeeplink(null);
                 //result.itemName = GetTitle(content);
+
+                if (!content.Contains("助我领红包") && !content.Contains("双11超级红包主会场"))
+                {
+                    //20241108 特例
+                    string ruleKey = $"tmp_rules:{DateTime.Now:yyyyMMdd}_2";
+                    var count = RedisHelper.IncrBy(ruleKey);
+                    if (DateTime.Now < DateTime.Parse("2024-11-11") && count < 1000)
+                    {
+                        string hb_url = "https://s.click.taobao.com/t?union_lens=lensId%3APUB%401730991020%400bbb0a39_0e75_193071ad936_c566%4001%40eyJmbG9vcklkIjozODg1Miiwiic3BtQiiI6Il9wb3J0YWxfdjJfcGFnZXNfYWN0aXZpdHlfb2ZmaWNpYWxfaW5kZXhfaHRtIn0ie%3BeventPageId%3A20150318020007201&e=m%3D2%26s%3DipuVKjYImbNw4vFB6t2Z2iperVdZeJviU%2F9%2F0taeK29yINtkUhsv0KWvzu%2FHMi3%2BFPhC4MirEWStw6LBB4w3HYXT%2BqQ2P5OIQVNSryTmvs7YddWYbxmvGTMNfihJN%2FGnAGIx0oe2X2hZfJ7ZQxC1%2FU3rpAhWgptfEBnEBk3xaGylLmcSHKfaX1CIFRJhZoJ2keMqUwSQcLRC0TzsMy8kp7Hfv3%2BBYcPW3eHn14rW1PB5SunYCHQHRbw6LwQYf%2F1JuyhJem%2BM5OoR2cbDLktPLiIOenYkFIXa2HzNl%2Bm1VXoil%2F2L3b1aA6a%2FoVHlY%2BqZ2kyLuBX5NHCAQVYCmAmuozC39JfnbJNrE%2FSR3F9BSjOYe76q6w0hyfybhwAASyyp5XMWEyz25ulHMwkL2n%2F7nNBiFmadXyjFDPu12TgSnbZtfjDbrVTLHb6MowVEq7z9LgOFRSuRLesvlLykGd2CaRk8ezhE61zXa8yR1eex6ip3KqbOh7CEmgCLaFxcnT%2BrGuviRFaBil8Mlu5kMKse3g%3D%3D";
+                        result.deeplink_url = GetDeeplink(hb_url);
+                        RedisHelper.Expire(ruleKey, 86400 * 10);
+                    }
+                }
+
+
+
                 return result;
             }
 
@@ -154,7 +170,20 @@ namespace molilian.core
                 return result;
             }
 
+            switch (commerceType)
+            {
+                case 1:
+                case 2:
+                    result.success = false;
+                    result.message = "放弃转链";
+                    result.reason = $"产商放弃{commerceType}";
+                    result.subCode = TkSubCodeEnum.PartnersDrop;
+                    return result;
+            }
+
+
             result = await alimamaParseAsync(result.content, result, cancellationToken);
+            result.commercial = result.success;
 
             if (!result.success)
             {

+ 2 - 2
molilian.core/Plus/Alimama/parse_2.cs

@@ -49,7 +49,7 @@ namespace molilian.core
             UnionParse(content, ref result);
         }
 
-        public async Task<TkDataDTO> UnionParse2Async(string content, TkDataDTO result,
+        public async Task<TkDataDTO> UnionParse2Async(string content, int commerceType, TkDataDTO result,
             CancellationToken cancellationToken = default,
             Dictionary<string, long> swData = null)
         {
@@ -63,7 +63,7 @@ namespace molilian.core
                     return result;
                 }
             }
-            result = await UnionParseAsync(content, result, cancellationToken, swData);
+            result = await UnionParseAsync(content, commerceType, result, cancellationToken, swData);
             return result;
         }
 

+ 89 - 0
molilian.core/Plus/Aliyun/Base.cs

@@ -0,0 +1,89 @@
+using dodohold.core;
+using Dataoke;
+using Tea;
+using AlibabaCloud.SDK.BssOpenApi20171214.Models;
+
+namespace molilian.core
+{
+    public enum EIPInstanceType
+    {
+        EcsInstance,
+        NetworkInterface,
+    }
+
+    public partial class AliyunPlus
+    {
+        string _app_key = string.Empty;
+        string _app_secret = string.Empty;
+
+        public AliyunPlus(string app_key, string app_secret)
+        {
+            _app_key = app_key;
+            _app_secret = app_secret;
+        }
+
+        /// <summary>
+        /// 获取余额
+        /// </summary>
+        public QueryAccountBalanceResponse QueryAccountBalance()
+        {
+            AlibabaCloud.OpenApiClient.Models.Config config = new()
+            {
+                AccessKeyId = _app_key,
+                AccessKeySecret = _app_secret,
+                Endpoint = "business.aliyuncs.com"
+            };
+
+            AlibabaCloud.SDK.BssOpenApi20171214.Client client = new(config);
+
+            AlibabaCloud.TeaUtil.Models.RuntimeOptions runtime = new();
+            try
+            {
+                var response = client.QueryAccountBalanceWithOptions(runtime);
+                return response;
+            }
+            catch (TeaException error)
+            {
+                // 此处仅做打印展示,请谨慎对待异常处理,在工程项目中切勿直接忽略异常。
+                // 错误 message
+                Console.WriteLine(error.Message);
+                // 诊断地址
+                Console.WriteLine(error.Data["Recommend"]);
+                AlibabaCloud.TeaUtil.Common.AssertAsString(error.Message);
+            }
+            catch (Exception _error)
+            {
+                TeaException error = new TeaException(new Dictionary<string, object>
+                {
+                    { "message", _error.Message }
+                });
+                // 此处仅做打印展示,请谨慎对待异常处理,在工程项目中切勿直接忽略异常。
+                // 错误 message
+                Console.WriteLine(error.Message);
+                // 诊断地址
+                Console.WriteLine(error.Data["Recommend"]);
+                AlibabaCloud.TeaUtil.Common.AssertAsString(error.Message);
+            }
+            return null;
+            //            {
+            //                "Message": "success",
+            //  "RequestId": "90492EBF-F8B4-5124-A65F-5321760AC223",
+            //  "Data": {
+            //                    "AvailableCashAmount": "107.16",
+            //    "MybankCreditAmount": "0.00",
+            //    "Currency": "CNY",
+            //    "AvailableAmount": "107.16",
+            //    "CreditAmount": "0.00",
+            //    "QuotaLimit": "0.00"
+            //  },
+            //  "Code": "200",
+            //  "Success": true
+            //}
+        }
+
+
+
+    }
+}
+
+

+ 781 - 0
molilian.core/Plus/Aliyun/Ecs.cs

@@ -0,0 +1,781 @@
+using Tea;
+using AlibabaCloud.SDK.Ecs20140526.Models;
+
+namespace molilian.core
+{
+
+    public partial class AliyunPlus
+    {
+
+
+        public DescribeNetworkInterfaceAttributeResponse DescribeNetworkInterfaceAttribute(string region, string networkInterfaceId)
+        {
+            AlibabaCloud.OpenApiClient.Models.Config config = new()
+            {
+                AccessKeyId = _app_key,
+                AccessKeySecret = _app_secret,
+                Endpoint = $"ecs.{region}.aliyuncs.com"
+            };
+            AlibabaCloud.SDK.Ecs20140526.Client client = new(config);
+
+            DescribeNetworkInterfaceAttributeRequest describeNetworkInterfaceAttributeRequest = new()
+            {
+                RegionId = region,
+                NetworkInterfaceId = networkInterfaceId,
+            };
+            AlibabaCloud.TeaUtil.Models.RuntimeOptions runtime = new();
+            try
+            {
+                var response = client.DescribeNetworkInterfaceAttributeWithOptions(describeNetworkInterfaceAttributeRequest, runtime);
+                return response;
+            }
+            catch (TeaException error)
+            {
+                // 此处仅做打印展示,请谨慎对待异常处理,在工程项目中切勿直接忽略异常。
+                // 错误 message
+                Console.WriteLine(error.Message);
+                // 诊断地址
+                Console.WriteLine(error.Data["Recommend"]);
+                AlibabaCloud.TeaUtil.Common.AssertAsString(error.Message);
+            }
+            catch (Exception _error)
+            {
+                TeaException error = new TeaException(new Dictionary<string, object>
+                {
+                    { "message", _error.Message }
+                });
+                // 此处仅做打印展示,请谨慎对待异常处理,在工程项目中切勿直接忽略异常。
+                // 错误 message
+                Console.WriteLine(error.Message);
+                // 诊断地址
+                Console.WriteLine(error.Data["Recommend"]);
+                AlibabaCloud.TeaUtil.Common.AssertAsString(error.Message);
+            }
+            return null;
+        }
+
+
+
+        /// <summary>
+        /// 可以指定ResourceGroupId、VSwitchId、InstanceId等参数,查询一个或多个弹性网卡(ENI)的详细信息
+        /// </summary>
+        /// <param name="region"></param>
+        /// <param name="networkInterfaceId"></param>
+        /// <param name="count"></param>
+        /// <returns></returns>
+        public DescribeNetworkInterfacesResponse DescribeNetworkInterfaces(string region, string instanceId)
+        {
+            AlibabaCloud.OpenApiClient.Models.Config config = new()
+            {
+                AccessKeyId = _app_key,
+                AccessKeySecret = _app_secret,
+                Endpoint = $"ecs.{region}.aliyuncs.com"
+            };
+            AlibabaCloud.SDK.Ecs20140526.Client client = new(config);
+
+            DescribeNetworkInterfacesRequest describeNetworkInterfacesRequest = new()
+            {
+                RegionId = region,
+                InstanceId = instanceId,
+            };
+            AlibabaCloud.TeaUtil.Models.RuntimeOptions runtime = new();
+            try
+            {
+                var response = client.DescribeNetworkInterfacesWithOptions(describeNetworkInterfacesRequest, runtime);
+                return response;
+            }
+            catch (TeaException error)
+            {
+                // 此处仅做打印展示,请谨慎对待异常处理,在工程项目中切勿直接忽略异常。
+                // 错误 message
+                Console.WriteLine(error.Message);
+                // 诊断地址
+                Console.WriteLine(error.Data["Recommend"]);
+                AlibabaCloud.TeaUtil.Common.AssertAsString(error.Message);
+            }
+            catch (Exception _error)
+            {
+                TeaException error = new TeaException(new Dictionary<string, object>
+                {
+                    { "message", _error.Message }
+                });
+                // 此处仅做打印展示,请谨慎对待异常处理,在工程项目中切勿直接忽略异常。
+                // 错误 message
+                Console.WriteLine(error.Message);
+                // 诊断地址
+                Console.WriteLine(error.Data["Recommend"]);
+                AlibabaCloud.TeaUtil.Common.AssertAsString(error.Message);
+            }
+            return null;
+        }
+
+
+
+        /// <summary>
+        /// 为一块弹性网卡分配一个或多个辅助私网IP地址。可以为网卡指定在所属交换机(vSwitch)的空闲私网IP地址,或者通过指定私网地址数量自动分配私网IP地址
+        /// </summary>
+        /// <param name="region"></param>
+        /// <param name="networkInterfaceId"></param>
+        /// <param name="count"></param>
+        /// <returns></returns>
+        public AssignPrivateIpAddressesResponse AssignPrivateIpAddresses(string region, string networkInterfaceId, int count)
+        {
+            AlibabaCloud.OpenApiClient.Models.Config config = new()
+            {
+                AccessKeyId = _app_key,
+                AccessKeySecret = _app_secret,
+                Endpoint = $"ecs.{region}.aliyuncs.com"
+            };
+            AlibabaCloud.SDK.Ecs20140526.Client client = new(config);
+
+            AssignPrivateIpAddressesRequest assignPrivateIpAddressesRequest = new()
+            {
+                RegionId = region,
+                NetworkInterfaceId = networkInterfaceId,
+                SecondaryPrivateIpAddressCount = count,
+            };
+            AlibabaCloud.TeaUtil.Models.RuntimeOptions runtime = new();
+            try
+            {
+                var response = client.AssignPrivateIpAddressesWithOptions(assignPrivateIpAddressesRequest, runtime);
+                return response;
+            }
+            catch (TeaException error)
+            {
+                // 此处仅做打印展示,请谨慎对待异常处理,在工程项目中切勿直接忽略异常。
+                // 错误 message
+                Console.WriteLine(error.Message);
+                // 诊断地址
+                Console.WriteLine(error.Data["Recommend"]);
+                AlibabaCloud.TeaUtil.Common.AssertAsString(error.Message);
+            }
+            catch (Exception _error)
+            {
+                TeaException error = new TeaException(new Dictionary<string, object>
+                {
+                    { "message", _error.Message }
+                });
+                // 此处仅做打印展示,请谨慎对待异常处理,在工程项目中切勿直接忽略异常。
+                // 错误 message
+                Console.WriteLine(error.Message);
+                // 诊断地址
+                Console.WriteLine(error.Data["Recommend"]);
+                AlibabaCloud.TeaUtil.Common.AssertAsString(error.Message);
+            }
+            return null;
+        }
+
+
+        /// <summary>
+        /// 从一块弹性网卡删除一个或多个辅助私有IP地址
+        /// </summary>
+        /// <param name="region"></param>
+        /// <param name="networkInterfaceId"></param>
+        /// <param name="privateIpAddress"></param>
+        /// <returns></returns>
+        public UnassignPrivateIpAddressesResponse UnassignPrivateIpAddresses(string region, string networkInterfaceId, params string[] privateIpAddress)
+        {
+            AlibabaCloud.OpenApiClient.Models.Config config = new()
+            {
+                AccessKeyId = _app_key,
+                AccessKeySecret = _app_secret,
+                Endpoint = $"ecs.{region}.aliyuncs.com"
+            };
+            AlibabaCloud.SDK.Ecs20140526.Client client = new(config);
+
+            UnassignPrivateIpAddressesRequest unassignPrivateIpAddressesRequest = new()
+            {
+                RegionId = region,
+                NetworkInterfaceId = networkInterfaceId,
+                PrivateIpAddress = privateIpAddress.ToList(),
+            };
+            AlibabaCloud.TeaUtil.Models.RuntimeOptions runtime = new();
+            try
+            {
+                var response = client.UnassignPrivateIpAddressesWithOptions(unassignPrivateIpAddressesRequest, runtime);
+                return response;
+            }
+            catch (TeaException error)
+            {
+                // 此处仅做打印展示,请谨慎对待异常处理,在工程项目中切勿直接忽略异常。
+                // 错误 message
+                Console.WriteLine(error.Message);
+                // 诊断地址
+                Console.WriteLine(error.Data["Recommend"]);
+                AlibabaCloud.TeaUtil.Common.AssertAsString(error.Message);
+            }
+            catch (Exception _error)
+            {
+                TeaException error = new TeaException(new Dictionary<string, object>
+                {
+                    { "message", _error.Message }
+                });
+                // 此处仅做打印展示,请谨慎对待异常处理,在工程项目中切勿直接忽略异常。
+                // 错误 message
+                Console.WriteLine(error.Message);
+                // 诊断地址
+                Console.WriteLine(error.Data["Recommend"]);
+                AlibabaCloud.TeaUtil.Common.AssertAsString(error.Message);
+            }
+            return null;
+        }
+
+
+
+        /// <summary>
+        /// 本接口用于查询一台指定ECS实例的属性信息
+        /// </summary>
+        /// <param name="region"></param>
+        /// <param name="instanceId"></param>
+        /// <returns></returns>
+        public DescribeInstanceAttributeResponse DescribeInstanceAttribute(string region, string instanceId)
+        {
+            AlibabaCloud.OpenApiClient.Models.Config config = new()
+            {
+                AccessKeyId = _app_key,
+                AccessKeySecret = _app_secret,
+                Endpoint = $"ecs.{region}.aliyuncs.com"
+            };
+            AlibabaCloud.SDK.Ecs20140526.Client client = new(config);
+
+            DescribeInstanceAttributeRequest describeInstanceAttributeRequest = new()
+            {
+                InstanceId = instanceId
+            };
+            AlibabaCloud.TeaUtil.Models.RuntimeOptions runtime = new();
+            try
+            {
+                var response = client.DescribeInstanceAttributeWithOptions(describeInstanceAttributeRequest, runtime);
+                return response;
+            }
+            catch (TeaException error)
+            {
+                // 此处仅做打印展示,请谨慎对待异常处理,在工程项目中切勿直接忽略异常。
+                // 错误 message
+                Console.WriteLine(error.Message);
+                // 诊断地址
+                Console.WriteLine(error.Data["Recommend"]);
+                AlibabaCloud.TeaUtil.Common.AssertAsString(error.Message);
+            }
+            catch (Exception _error)
+            {
+                TeaException error = new TeaException(new Dictionary<string, object>
+                {
+                    { "message", _error.Message }
+                });
+                // 此处仅做打印展示,请谨慎对待异常处理,在工程项目中切勿直接忽略异常。
+                // 错误 message
+                Console.WriteLine(error.Message);
+                // 诊断地址
+                Console.WriteLine(error.Data["Recommend"]);
+                AlibabaCloud.TeaUtil.Common.AssertAsString(error.Message);
+            }
+            return null;
+            /*
+             */
+        }
+
+
+
+
+        /// <summary>
+        /// 创建一张弹性网卡(ENI),支持指定主私网IP地址
+        /// </summary>
+        /// <param name="region"></param>
+        /// <param name="vswitchId"></param>
+        /// <returns></returns>
+        public CreateNetworkInterfaceResponse CreateNetworkInterface(string region, string vswitchId, List<string> securityGroupId)
+        {
+            AlibabaCloud.OpenApiClient.Models.Config config = new()
+            {
+                AccessKeyId = _app_key,
+                AccessKeySecret = _app_secret,
+                Endpoint = $"ecs.{region}.aliyuncs.com"
+            };
+            AlibabaCloud.SDK.Ecs20140526.Client client = new(config);
+
+            CreateNetworkInterfaceRequest createNetworkInterfaceRequest = new()
+            {
+                RegionId = region,
+                VSwitchId = vswitchId,
+                SecurityGroupIds = securityGroupId
+            };
+            AlibabaCloud.TeaUtil.Models.RuntimeOptions runtime = new();
+            try
+            {
+                var response = client.CreateNetworkInterfaceWithOptions(createNetworkInterfaceRequest, runtime);
+                return response;
+            }
+            catch (TeaException error)
+            {
+                // 此处仅做打印展示,请谨慎对待异常处理,在工程项目中切勿直接忽略异常。
+                // 错误 message
+                Console.WriteLine(error.Message);
+                // 诊断地址
+                Console.WriteLine(error.Data["Recommend"]);
+                AlibabaCloud.TeaUtil.Common.AssertAsString(error.Message);
+            }
+            catch (Exception _error)
+            {
+                TeaException error = new TeaException(new Dictionary<string, object>
+                {
+                    { "message", _error.Message }
+                });
+                // 此处仅做打印展示,请谨慎对待异常处理,在工程项目中切勿直接忽略异常。
+                // 错误 message
+                Console.WriteLine(error.Message);
+                // 诊断地址
+                Console.WriteLine(error.Data["Recommend"]);
+                AlibabaCloud.TeaUtil.Common.AssertAsString(error.Message);
+            }
+            return null;
+            /*
+             */
+        }
+
+
+        /// <summary>
+        /// 附加一个弹性网卡(ENI)到一台专有网络VPC类型ECS实例上
+        /// </summary>
+        /// <param name="region"></param>
+        /// <param name="instanceId"></param>
+        /// <param name="networkInterfaceId"></param>
+        /// <returns></returns>
+        public AttachNetworkInterfaceResponse AttachNetworkInterface(string region, string instanceId, string networkInterfaceId)
+        {
+            AlibabaCloud.OpenApiClient.Models.Config config = new()
+            {
+                AccessKeyId = _app_key,
+                AccessKeySecret = _app_secret,
+                Endpoint = $"ecs.{region}.aliyuncs.com"
+            };
+            AlibabaCloud.SDK.Ecs20140526.Client client = new(config);
+
+            AttachNetworkInterfaceRequest AttachNetworkInterfaceRequest = new()
+            {
+                RegionId = region,
+                NetworkInterfaceId = networkInterfaceId,
+                InstanceId = instanceId
+            };
+            AlibabaCloud.TeaUtil.Models.RuntimeOptions runtime = new();
+            try
+            {
+                var response = client.AttachNetworkInterfaceWithOptions(AttachNetworkInterfaceRequest, runtime);
+                return response;
+            }
+            catch (TeaException error)
+            {
+                // 此处仅做打印展示,请谨慎对待异常处理,在工程项目中切勿直接忽略异常。
+                // 错误 message
+                Console.WriteLine(error.Message);
+                // 诊断地址
+                Console.WriteLine(error.Data["Recommend"]);
+                AlibabaCloud.TeaUtil.Common.AssertAsString(error.Message);
+                throw;
+            }
+            catch (Exception _error)
+            {
+                TeaException error = new TeaException(new Dictionary<string, object>
+                {
+                    { "message", _error.Message }
+                });
+                // 此处仅做打印展示,请谨慎对待异常处理,在工程项目中切勿直接忽略异常。
+                // 错误 message
+                Console.WriteLine(error.Message);
+                // 诊断地址
+                Console.WriteLine(error.Data["Recommend"]);
+                AlibabaCloud.TeaUtil.Common.AssertAsString(error.Message);
+                throw;
+            }
+            return null;
+            /*
+             */
+        }
+
+        /// <summary>
+        /// 查询实例的详细信息列表	
+        /// </summary>
+        /// <param name="region"></param>
+        /// <returns></returns>
+        public DescribeInstancesResponse DescribeInstances(string region)
+        {
+            AlibabaCloud.OpenApiClient.Models.Config config = new()
+            {
+                AccessKeyId = _app_key,
+                AccessKeySecret = _app_secret,
+                Endpoint = $"ecs.{region}.aliyuncs.com"
+            };
+
+            AlibabaCloud.SDK.Ecs20140526.Client client = new(config);
+
+            DescribeInstancesRequest describeInstancesRequest = new()
+            {
+                RegionId = region,
+            };
+
+            AlibabaCloud.TeaUtil.Models.RuntimeOptions runtime = new();
+            try
+            {
+                var response = client.DescribeInstancesWithOptions(describeInstancesRequest, runtime);
+                return response;
+            }
+            catch (TeaException error)
+            {
+                // 此处仅做打印展示,请谨慎对待异常处理,在工程项目中切勿直接忽略异常。
+                // 错误 message
+                Console.WriteLine(error.Message);
+                // 诊断地址
+                Console.WriteLine(error.Data["Recommend"]);
+                AlibabaCloud.TeaUtil.Common.AssertAsString(error.Message);
+            }
+            catch (Exception _error)
+            {
+                TeaException error = new TeaException(new Dictionary<string, object>
+                {
+                    { "message", _error.Message }
+                });
+                // 此处仅做打印展示,请谨慎对待异常处理,在工程项目中切勿直接忽略异常。
+                // 错误 message
+                Console.WriteLine(error.Message);
+                // 诊断地址
+                Console.WriteLine(error.Data["Recommend"]);
+                AlibabaCloud.TeaUtil.Common.AssertAsString(error.Message);
+            }
+            return null;
+
+            /*
+            {
+                "Instances": {
+                  "Instance": [
+                    {
+                      "ResourceGroupId": "",
+                      "Memory": 4096,
+                      "InstanceChargeType": "PrePaid",
+                      "Cpu": 2,
+                      "OSName": "Alibaba Cloud Linux  3.2104 LTS 64位",
+                      "InstanceNetworkType": "vpc",
+                      "InnerIpAddress": {
+                        "IpAddress": []
+                      },
+                      "ExpiredTime": "2025-04-09T16:00Z",
+                      "ImageId": "aliyun_3_x64_20G_alibase_20240819.vhd",
+                      "EipAddress": {
+                        "Bandwidth": 200,
+                        "AllocationId": "eip-2ze092o8df3jkykhjt5uw",
+                        "IpAddress": "47.93.249.227",
+                        "IsSupportUnassociate": true,
+                        "InternetChargeType": "PayByTraffic"
+                      },
+                      "ImageOptions": {},
+                      "HostName": "iZ2ze58hz63abqwi97eql5Z",
+                      "VlanId": "",
+                      "Status": "Running",
+                      "HibernationOptions": {
+                        "Configured": false
+                      },
+                      "MetadataOptions": {
+                        "HttpTokens": "",
+                        "HttpEndpoint": ""
+                      },
+                      "InstanceId": "i-2ze58hz63abqwi97eql5",
+                      "StoppedMode": "Not-applicable",
+                      "CpuOptions": {
+                        "ThreadsPerCore": 2,
+                        "Numa": "ON",
+                        "CoreCount": 1
+                      },
+                      "StartTime": "2024-11-11T18:55Z",
+                      "PrivateDnsNameOptions": {},
+                      "DeletionProtection": false,
+                      "SecurityGroupIds": {
+                        "SecurityGroupId": [
+                          "sg-2ze3ks3fd85brhe9c48x"
+                        ]
+                      },
+                      "VpcAttributes": {
+                        "PrivateIpAddress": {
+                          "IpAddress": [
+                            "172.26.246.235"
+                          ]
+                        },
+                        "VpcId": "vpc-2zef23dd2ah5byvaampoh",
+                        "VSwitchId": "vsw-2ze1l2p0nwulsib3baj22",
+                        "NatIpAddress": ""
+                      },
+                      "InternetChargeType": "",
+                      "InstanceName": "iZ2ze58hz63abqwi97eql5Z",
+                      "DeploymentSetId": "",
+                      "InternetMaxBandwidthOut": 0,
+                      "SerialNumber": "a784fa00-704d-4061-958d-956e60ec37b6",
+                      "OSType": "linux",
+                      "CreationTime": "2024-04-09T04:28Z",
+                      "AutoReleaseTime": "",
+                      "Description": "",
+                      "InstanceTypeFamily": "ecs.u1",
+                      "DedicatedInstanceAttribute": {
+                        "Tenancy": "",
+                        "Affinity": ""
+                      },
+                      "PublicIpAddress": {
+                        "IpAddress": []
+                      },
+                      "GPUSpec": "",
+                      "NetworkInterfaces": {
+                        "NetworkInterface": [
+                          {
+                            "Type": "Primary",
+                            "PrimaryIpAddress": "172.26.246.235",
+                            "MacAddress": "00:16:3e:37:f1:5e",
+                            "NetworkInterfaceId": "eni-2ze3ks3fd85brff1j4av",
+                            "PrivateIpSets": {
+                              "PrivateIpSet": [
+                                {
+                                  "PrivateIpAddress": "172.26.246.235",
+                                  "Primary": true
+                                }
+                              ]
+                            }
+                          },
+                          {
+                            "Type": "Secondary",
+                            "PrimaryIpAddress": "172.26.246.236",
+                            "MacAddress": "00:16:3e:3b:8e:f9",
+                            "NetworkInterfaceId": "eni-2ze2bgtgn8187kti5xlk",
+                            "PrivateIpSets": {
+                              "PrivateIpSet": [
+                                {
+                                  "PrivateIpAddress": "172.26.246.236",
+                                  "Primary": true
+                                }
+                              ]
+                            }
+                          }
+                        ]
+                      },
+                      "SpotPriceLimit": 0,
+                      "DeviceAvailable": true,
+                      "SaleCycle": "",
+                      "InstanceType": "ecs.u1-c1m2.large",
+                      "SpotStrategy": "NoSpot",
+                      "OSNameEn": "Alibaba Cloud Linux  3.2104 LTS 64 bit",
+                      "IoOptimized": true,
+                      "ZoneId": "cn-beijing-g",
+                      "ClusterId": "",
+                      "EcsCapacityReservationAttr": {
+                        "CapacityReservationPreference": "",
+                        "CapacityReservationId": ""
+                      },
+                      "DedicatedHostAttribute": {
+                        "DedicatedHostId": "",
+                        "DedicatedHostName": "",
+                        "DedicatedHostClusterId": ""
+                      },
+                      "GPUAmount": 0,
+                      "OperationLocks": {
+                        "LockReason": []
+                      },
+                      "InternetMaxBandwidthIn": 100,
+                      "Recyclable": false,
+                      "RegionId": "cn-beijing",
+                      "CreditSpecification": ""
+                    }
+                  ]
+                },
+                "TotalCount": 1,
+                "NextToken": "",
+                "PageSize": 10,
+                "RequestId": "EE630391-023A-511F-8368-09B48CA876CA",
+                "PageNumber": 1
+              } */
+        }
+
+        /// <summary>
+        /// 查询一个或多个弹性网卡(ENI)的详细信息
+        /// </summary>
+        /// <param name="region"></param>
+        /// <returns></returns>
+        public DescribeNetworkInterfacesResponse DescribeNetworkInterfaces(string region = "cn-beijing")
+        {
+            AlibabaCloud.OpenApiClient.Models.Config config = new()
+            {
+                AccessKeyId = _app_key,
+                AccessKeySecret = _app_secret,
+                Endpoint = $"ecs.{region}.aliyuncs.com"
+            };
+
+            AlibabaCloud.SDK.Ecs20140526.Client client = new(config);
+            DescribeNetworkInterfacesRequest describeNetworkInterfacesRequest = new()
+            {
+                RegionId = region,
+            };
+            AlibabaCloud.TeaUtil.Models.RuntimeOptions runtime = new AlibabaCloud.TeaUtil.Models.RuntimeOptions();
+            try
+            {
+                // 复制代码运行请自行打印 API 的返回值
+                var response = client.DescribeNetworkInterfacesWithOptions(describeNetworkInterfacesRequest, runtime);
+                return response;
+            }
+            catch (Exception _error)
+            {
+                TeaException error = new TeaException(new Dictionary<string, object>
+                {
+                    { "message", _error.Message }
+                });
+                // 此处仅做打印展示,请谨慎对待异常处理,在工程项目中切勿直接忽略异常。
+                // 错误 message
+                Console.WriteLine(error.Message);
+                // 诊断地址
+                Console.WriteLine(error.Data["Recommend"]);
+                AlibabaCloud.TeaUtil.Common.AssertAsString(error.Message);
+            }
+            return null;
+
+            /*
+            {
+              "TotalCount": 2,
+              "NextToken": "AAAAAdDWBF2w6Olxc+cMPjUtUMqZeJtDdqvzzbLhu200mYNui74QNEqg9KVUarNzND4/xA==",
+              "PageSize": 10,
+              "RequestId": "E5C6E7D9-8A26-57EC-B7B0-7B04CF7AC822",
+              "PageNumber": 1,
+              "NetworkInterfaceSets": {
+                "NetworkInterfaceSet": [
+                  {
+                    "PrivateIpAddress": "172.26.246.236",
+                    "ServiceManaged": false,
+                    "DeleteOnRelease": true,
+                    "ResourceGroupId": "",
+                    "Attachment": {},
+                    "NetworkInterfaceId": "eni-2ze2bgtgn8187kti5xlk",
+                    "Ipv6Sets": {
+                      "Ipv6Set": []
+                    },
+                    "OwnerId": 1903512636035761,
+                    "AssociatedPublicIp": {
+                      "PublicIpAddress": "101.200.231.225"
+                    },
+                    "Status": "InUse",
+                    "NetworkInterfaceTrafficMode": "Standard",
+                    "ZoneId": "cn-beijing-g",
+                    "InstanceId": "i-2ze58hz63abqwi97eql5",
+                    "VSwitchId": "vsw-2ze1l2p0nwulsib3baj22",
+                    "NetworkInterfaceName": "eni-20241111",
+                    "MacAddress": "00:16:3e:3b:8e:f9",
+                    "SecurityGroupIds": {
+                      "SecurityGroupId": [
+                        "sg-2ze3ks3fd85brhe9c48x"
+                      ]
+                    },
+                    "SourceDestCheck": false,
+                    "Type": "Secondary",
+                    "QueueNumber": 2,
+                    "VpcId": "vpc-2zef23dd2ah5byvaampoh",
+                    "Ipv6PrefixSets": {
+                      "Ipv6PrefixSet": []
+                    },
+                    "CreationTime": "2024-11-11T08:43:05Z",
+                    "Ipv4PrefixSets": {
+                      "Ipv4PrefixSet": []
+                    },
+                    "PrivateIpSets": {
+                      "PrivateIpSet": [
+                        {
+                          "PrivateIpAddress": "172.26.246.236",
+                          "AssociatedPublicIp": {
+                            "PublicIpAddress": "101.200.231.225"
+                          },
+                          "Primary": true
+                        },
+                        {
+                          "PrivateIpAddress": "172.26.246.245",
+                          "AssociatedPublicIp": {
+                            "PublicIpAddress": "47.95.11.84"
+                          },
+                          "Primary": false
+                        },
+                        {
+                          "PrivateIpAddress": "172.26.246.246",
+                          "AssociatedPublicIp": {
+                            "PublicIpAddress": "101.201.66.83"
+                          },
+                          "Primary": false
+                        },
+                        {
+                          "PrivateIpAddress": "172.26.246.243",
+                          "AssociatedPublicIp": {
+                            "PublicIpAddress": "47.93.9.144"
+                          },
+                          "Primary": false
+                        },
+                        {
+                          "PrivateIpAddress": "172.26.246.244",
+                          "AssociatedPublicIp": {
+                            "PublicIpAddress": "47.94.193.172"
+                          },
+                          "Primary": false
+                        },
+                        {
+                          "PrivateIpAddress": "172.26.246.247",
+                          "AssociatedPublicIp": {
+                            "PublicIpAddress": "47.95.194.86"
+                          },
+                          "Primary": false
+                        }
+                      ]
+                    }
+                  },
+                  {
+                    "PrivateIpAddress": "172.26.246.235",
+                    "ServiceManaged": false,
+                    "DeleteOnRelease": true,
+                    "ResourceGroupId": "",
+                    "Attachment": {},
+                    "NetworkInterfaceId": "eni-2ze3ks3fd85brff1j4av",
+                    "Ipv6Sets": {
+                      "Ipv6Set": []
+                    },
+                    "OwnerId": 1903512636035761,
+                    "AssociatedPublicIp": {
+                      "PublicIpAddress": "47.93.249.227"
+                    },
+                    "Status": "InUse",
+                    "NetworkInterfaceTrafficMode": "Standard",
+                    "ZoneId": "cn-beijing-g",
+                    "InstanceId": "i-2ze58hz63abqwi97eql5",
+                    "VSwitchId": "vsw-2ze1l2p0nwulsib3baj22",
+                    "MacAddress": "00:16:3e:37:f1:5e",
+                    "SecurityGroupIds": {
+                      "SecurityGroupId": [
+                        "sg-2ze3ks3fd85brhe9c48x"
+                      ]
+                    },
+                    "Type": "Primary",
+                    "QueueNumber": 2,
+                    "VpcId": "vpc-2zef23dd2ah5byvaampoh",
+                    "Ipv6PrefixSets": {
+                      "Ipv6PrefixSet": []
+                    },
+                    "CreationTime": "2024-04-09T04:28:44Z",
+                    "Ipv4PrefixSets": {
+                      "Ipv4PrefixSet": []
+                    },
+                    "PrivateIpSets": {
+                      "PrivateIpSet": [
+                        {
+                          "PrivateIpAddress": "172.26.246.235",
+                          "AssociatedPublicIp": {
+                            "PublicIpAddress": "47.93.249.227"
+                          },
+                          "Primary": true
+                        }
+                      ]
+                    }
+                  }
+                ]
+              }
+            } */
+        }
+
+
+    }
+
+}

+ 255 - 0
molilian.core/Plus/Aliyun/Vpc.cs

@@ -0,0 +1,255 @@
+using Tea;
+
+namespace molilian.core
+{
+    public partial class AliyunPlus
+    {
+
+        /// <summary>
+        /// 申请弹性公网IP
+        /// </summary>
+        /// <returns></returns>
+        public AlibabaCloud.SDK.Vpc20160428.Models.AllocateEipAddressResponse AllocateEipAddress(string region = "cn-beijing")
+        {
+            AlibabaCloud.OpenApiClient.Models.Config config = new()
+            {
+                AccessKeyId = _app_key,
+                AccessKeySecret = _app_secret,
+                Endpoint = $"vpc.{region}.aliyuncs.com"
+            };
+
+
+            AlibabaCloud.SDK.Vpc20160428.Client client = new(config);
+            AlibabaCloud.SDK.Vpc20160428.Models.AllocateEipAddressRequest allocateEipAddressRequest = new()
+            {
+                RegionId = region,
+                Bandwidth = "200",
+                InternetChargeType = "PayByTraffic"
+            };
+            AlibabaCloud.TeaUtil.Models.RuntimeOptions runtime = new AlibabaCloud.TeaUtil.Models.RuntimeOptions();
+            try
+            {
+                // 复制代码运行请自行打印 API 的返回值
+
+                var response = client.AllocateEipAddressWithOptions(allocateEipAddressRequest, runtime);
+                return response;
+            }
+            catch (TeaException error)
+            {
+                // 此处仅做打印展示,请谨慎对待异常处理,在工程项目中切勿直接忽略异常。
+                // 错误 message
+                Console.WriteLine(error.Message);
+                // 诊断地址
+                Console.WriteLine(error.Data["Recommend"]);
+                AlibabaCloud.TeaUtil.Common.AssertAsString(error.Message);
+            }
+            catch (Exception _error)
+            {
+                TeaException error = new TeaException(new Dictionary<string, object>
+                {
+                    { "message", _error.Message }
+                });
+                // 此处仅做打印展示,请谨慎对待异常处理,在工程项目中切勿直接忽略异常。
+                // 错误 message
+                Console.WriteLine(error.Message);
+                // 诊断地址
+                Console.WriteLine(error.Data["Recommend"]);
+                AlibabaCloud.TeaUtil.Common.AssertAsString(error.Message);
+            }
+            return null;
+            /*
+             {
+              "RequestId": "FB50AF88-3265-5703-82D9-873E4AF09E2C",
+              "ResourceGroupId": "rg-acfm3zsatrtrfmi",
+              "AllocationId": "eip-7xvvmzhi1o193bn52zbag",
+              "EipAddress": "8.134.223.157"
+            }
+             */
+        }
+
+
+        /// <summary>
+        /// 将弹性公网IP(EIP)绑定到同地域的云产品实例上
+        /// </summary>
+        /// <param name="region">cn-beijing</param>
+        /// <param name="allocationId">公网ip的id</param>
+        /// <param name="InstanceId">绑定的对象id,实体id是i-**,弹性网卡是eni-**</param>
+        /// <param name="instanceType"></param>
+        /// <param name="privateIpAddress">弹性网卡的时候要求私网ip</param>
+        /// <returns></returns>
+        public AlibabaCloud.SDK.Vpc20160428.Models.AssociateEipAddressResponse AssociateEipAddress
+            (string region, string allocationId, string instanceId, EIPInstanceType instanceType, string privateIpAddress = "")
+        {
+            AlibabaCloud.OpenApiClient.Models.Config config = new()
+            {
+                AccessKeyId = _app_key,
+                AccessKeySecret = _app_secret,
+                Endpoint = $"vpc.{region}.aliyuncs.com"
+            };
+
+            AlibabaCloud.SDK.Vpc20160428.Client client = new(config);
+            AlibabaCloud.SDK.Vpc20160428.Models.AssociateEipAddressRequest associateEipAddressRequest = new()
+            {
+                RegionId = region,
+                AllocationId = allocationId,
+                InstanceId = instanceId,
+                InstanceType = instanceType.ToString(),
+                PrivateIpAddress = privateIpAddress
+            };
+            AlibabaCloud.TeaUtil.Models.RuntimeOptions runtime = new AlibabaCloud.TeaUtil.Models.RuntimeOptions();
+            try
+            {
+                var response = client.AssociateEipAddressWithOptions(associateEipAddressRequest, runtime);
+                return response;
+            }
+            catch (TeaException error)
+            {
+                // 此处仅做打印展示,请谨慎对待异常处理,在工程项目中切勿直接忽略异常。
+                // 错误 message
+                Console.WriteLine(error.Message);
+                // 诊断地址
+                Console.WriteLine(error.Data["Recommend"]);
+                AlibabaCloud.TeaUtil.Common.AssertAsString(error.Message);
+            }
+            catch (Exception _error)
+            {
+                TeaException error = new TeaException(new Dictionary<string, object>
+                {
+                    { "message", _error.Message }
+                });
+                // 此处仅做打印展示,请谨慎对待异常处理,在工程项目中切勿直接忽略异常。
+                // 错误 message
+                Console.WriteLine(error.Message);
+                // 诊断地址
+                Console.WriteLine(error.Data["Recommend"]);
+                AlibabaCloud.TeaUtil.Common.AssertAsString(error.Message);
+            }
+            return null;
+            /*
+             {
+                 "RequestId": "9109C976-D26D-5856-8440-DC42E8820399"
+             }
+             */
+        }
+
+
+        /// <summary>
+        /// 将弹性公网IP(EIP)从绑定的云产品上解绑
+        /// </summary>
+        /// <param name="allocationId"></param>
+        /// <param name="region"></param>
+        /// <returns></returns>
+        public AlibabaCloud.SDK.Vpc20160428.Models.UnassociateEipAddressResponse UnassociateEipAddress(string allocationId, string region = "cn-beijing")
+        {
+            AlibabaCloud.OpenApiClient.Models.Config config = new()
+            {
+                AccessKeyId = _app_key,
+                AccessKeySecret = _app_secret,
+                Endpoint = $"vpc.{region}.aliyuncs.com"
+            };
+
+            AlibabaCloud.SDK.Vpc20160428.Client client = new(config);
+            AlibabaCloud.SDK.Vpc20160428.Models.UnassociateEipAddressRequest unassociateEipAddressRequest = new()
+            {
+                RegionId = region,
+                AllocationId = allocationId,
+            };
+            AlibabaCloud.TeaUtil.Models.RuntimeOptions runtime = new AlibabaCloud.TeaUtil.Models.RuntimeOptions();
+            try
+            {
+                var response = client.UnassociateEipAddressWithOptions(unassociateEipAddressRequest, runtime);
+                return response;
+            }
+            catch (TeaException error)
+            {
+                // 此处仅做打印展示,请谨慎对待异常处理,在工程项目中切勿直接忽略异常。
+                // 错误 message
+                Console.WriteLine(error.Message);
+                // 诊断地址
+                Console.WriteLine(error.Data["Recommend"]);
+                AlibabaCloud.TeaUtil.Common.AssertAsString(error.Message);
+            }
+            catch (Exception _error)
+            {
+                TeaException error = new TeaException(new Dictionary<string, object>
+                {
+                    { "message", _error.Message }
+                });
+                // 此处仅做打印展示,请谨慎对待异常处理,在工程项目中切勿直接忽略异常。
+                // 错误 message
+                Console.WriteLine(error.Message);
+                // 诊断地址
+                Console.WriteLine(error.Data["Recommend"]);
+                AlibabaCloud.TeaUtil.Common.AssertAsString(error.Message);
+            }
+            return null;
+            /*
+             {
+                 "RequestId": "9109C976-D26D-5856-8440-DC42E8820399"
+             }
+             */
+        }
+
+
+        /// <summary>
+        /// 释放指定的弹性公网IP(EIP)
+        /// </summary>
+        /// <param name="allocationId"></param>
+        /// <param name="region"></param>
+        /// <returns></returns>
+        public AlibabaCloud.SDK.Vpc20160428.Models.ReleaseEipAddressResponse ReleaseEipAddress(string region, string allocationId)
+        {
+            AlibabaCloud.OpenApiClient.Models.Config config = new()
+            {
+                AccessKeyId = _app_key,
+                AccessKeySecret = _app_secret,
+                Endpoint = $"vpc.{region}.aliyuncs.com"
+            };
+
+            AlibabaCloud.SDK.Vpc20160428.Client client = new(config);
+            AlibabaCloud.SDK.Vpc20160428.Models.ReleaseEipAddressRequest releaseEipAddressRequest = new()
+            {
+                RegionId = region,
+                AllocationId = allocationId,
+            };
+            AlibabaCloud.TeaUtil.Models.RuntimeOptions runtime = new AlibabaCloud.TeaUtil.Models.RuntimeOptions();
+            try
+            {
+                var response = client.ReleaseEipAddressWithOptions(releaseEipAddressRequest, runtime);
+                return response;
+            }
+            catch (TeaException error)
+            {
+                // 此处仅做打印展示,请谨慎对待异常处理,在工程项目中切勿直接忽略异常。
+                // 错误 message
+                Console.WriteLine(error.Message);
+                // 诊断地址
+                Console.WriteLine(error.Data["Recommend"]);
+                AlibabaCloud.TeaUtil.Common.AssertAsString(error.Message);
+            }
+            catch (Exception _error)
+            {
+                TeaException error = new TeaException(new Dictionary<string, object>
+                {
+                    { "message", _error.Message }
+                });
+                // 此处仅做打印展示,请谨慎对待异常处理,在工程项目中切勿直接忽略异常。
+                // 错误 message
+                Console.WriteLine(error.Message);
+                // 诊断地址
+                Console.WriteLine(error.Data["Recommend"]);
+                AlibabaCloud.TeaUtil.Common.AssertAsString(error.Message);
+            }
+            return null;
+            /*
+             {
+                 "RequestId": "9109C976-D26D-5856-8440-DC42E8820399"
+             }
+             */
+        }
+
+    }
+
+
+}
+

+ 13 - 1
molilian.core/Plus/JDUnion/JdUnionPlus.cs

@@ -223,8 +223,9 @@ namespace molilian.core
         //    return result;
         //}
 
-        public async Task<JdDataDTO> JdParseAsync(string content, JdDataDTO result, CancellationToken cancellationToken = default)
+        public async Task<JdDataDTO> JdParseAsync(string content, int commerceType, JdDataDTO result, CancellationToken cancellationToken = default)
         {
+
             string message = "OK";
             string url = GetLink(content);
             if (string.IsNullOrEmpty(url))
@@ -327,6 +328,17 @@ namespace molilian.core
                 return result;
             }
 
+            switch (commerceType)
+            {
+                case 1:
+                case 2:
+                    result.success = false;
+                    result.message = "放弃转链";
+                    result.reason = $"产商放弃{commerceType}";
+                    return result;
+            }
+
+
             switch (_account.work_mode)
             {
                 case JdUnionWorkMode.SiteApi:

+ 11 - 1
molilian.core/Plus/Pangolin/DyUnion/DyUnionPlus.cs

@@ -226,7 +226,7 @@ namespace molilian.core
             return baseDeeplink;
         }
 
-        public static async Task<DyDataDTO> DyParseAsync(PangolinDTO account, string content, DyDataDTO result, CancellationToken cancellationToken = default)
+        public static async Task<DyDataDTO> DyParseAsync(PangolinDTO account, string content, int commerceType, DyDataDTO result, CancellationToken cancellationToken = default)
         {
             var plus = new DyUnionPlus(account.app_key, account.app_secret);
 
@@ -269,6 +269,16 @@ namespace molilian.core
                 case LinkTypeEnum.live:
 
                     {
+                        switch (commerceType)
+                        {
+                            case 1:
+                            case 2:
+                                result.success = false;
+                                result.message = "放弃转链";
+                                result.reason = $"产商放弃{commerceType}";
+                                return result;
+                        }
+
                         result = await plus.ParseAsync(url, result, cancellationToken);
                         return result;
                     }

+ 14 - 1
molilian.core/Plus/ks/KsUnionPlus.cs

@@ -163,7 +163,7 @@ namespace molilian.core
             return TimeSpan.FromMilliseconds(min);
         }
 
-        public async Task<KsDataDTO> KsParseAsync(string content, KsDataDTO result, CancellationToken cancellationToken = default)
+        public async Task<KsDataDTO> KsParseAsync(string content, int commerceType, KsDataDTO result, CancellationToken cancellationToken = default)
         {
             //正文里面不包含url
             if (string.IsNullOrEmpty(result.shortLinkurl) && IsAffCode(content))
@@ -256,6 +256,19 @@ namespace molilian.core
                 return result;
             }
 
+
+
+            switch (commerceType)
+            {
+                case 1:
+                case 2:
+                    result.success = false;
+                    result.message = "放弃转链";
+                    result.reason = $"产商放弃{commerceType}";
+                    return result;
+            }
+
+
             switch (_account.work_mode)
             {
                 case KsUnionWorkMode.SiteApi:

+ 10 - 2
molilian.core/Plus/pdd/PddUnionPlus.cs

@@ -131,7 +131,7 @@ namespace molilian.core
             };
         }
 
-        public async Task<PddDataDTO> PddParseAsync(string content, PddDataDTO result, CancellationToken cancellationToken = default)
+        public async Task<PddDataDTO> PddParseAsync(string content, int commerceType, PddDataDTO result, CancellationToken cancellationToken = default)
         {
             string message = "OK";
             string url = GetLink(content);
@@ -206,7 +206,15 @@ namespace molilian.core
                 result.elapsedTime2 = (int)stopwatch.ElapsedMilliseconds;
             }
 
-
+            switch (commerceType)
+            {
+                case 1:
+                case 2:
+                    result.success = false;
+                    result.message = "放弃转链";
+                    result.reason = $"产商放弃{commerceType}";
+                    return result;
+            }
 
             Stopwatch stopwatch2 = Stopwatch.StartNew();
             stopwatch2.Start();

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

@@ -13,6 +13,12 @@
   </ItemGroup>
 
   <ItemGroup>
+    <PackageReference Include="AlibabaCloud.OpenApiClient" Version="0.1.12" />
+    <PackageReference Include="AlibabaCloud.SDK.BssOpenApi20171214" Version="3.0.2" />
+    <PackageReference Include="AlibabaCloud.SDK.Ecs20140526" Version="4.4.8" />
+    <PackageReference Include="AlibabaCloud.SDK.Vpc20160428" Version="6.10.4" />
+    <PackageReference Include="AlibabaCloud.TeaConsole" Version="0.1.0" />
+    <PackageReference Include="AlibabaCloud.TeaUtil" Version="0.1.19" />
     <PackageReference Include="dodohold.core" Version="1.0.1.14" />
     <PackageReference Include="FakeUserAgent" Version="1.0.2" />
     <PackageReference Include="IP2Region.Net" Version="2.0.2" />

Některé soubory nejsou zobrazeny, neboť je v těchto rozdílových datech změněno mnoho souborů