|
|
@@ -1,104 +1,580 @@
|
|
|
-using molilian.core;
|
|
|
-using dodohold.core;
|
|
|
-using Microsoft.AspNetCore.Mvc;
|
|
|
-using Org.BouncyCastle.Ocsp;
|
|
|
-using System.Text.Json;
|
|
|
-using System.Runtime.InteropServices;
|
|
|
-using TencentCloud.Scf.V20180416.Models;
|
|
|
-using Quartz.Impl.AdoJobStore.Common;
|
|
|
-using TencentCloud.Gaap.V20180529.Models;
|
|
|
-using System.Net;
|
|
|
-using TencentCloud.Ie.V20200304.Models;
|
|
|
-using TencentCloud.Soe.V20180724.Models;
|
|
|
-
|
|
|
-namespace molilian.api.Controllers
|
|
|
-{
|
|
|
- [ApiController]
|
|
|
- [MyAuthorize("admin")]
|
|
|
- [Route("api/[controller]/[action]")]
|
|
|
- public class ProxyController : ControllerBase
|
|
|
- {
|
|
|
- readonly IAuthorizationProvider provider = new AdminProvider();
|
|
|
- protected IHttpContextAccessor _accessor;
|
|
|
- public ProxyController(IHttpContextAccessor accessor)
|
|
|
- {
|
|
|
- _accessor = accessor;
|
|
|
- }
|
|
|
-
|
|
|
- [HttpGet]
|
|
|
- public ActionResult get()
|
|
|
- {
|
|
|
- var list = new DBContext.Table("proxy_nodes")
|
|
|
- .Where("status=@status", new { status = 1 })
|
|
|
- .Select<ProxyNodesDTO>();
|
|
|
-
|
|
|
- // ćèæ°æź
|
|
|
- //61 1 6 ćé
245 ćé
èŸ
ć©çœćĄ bj http http://172.21.127.245:33128 molilian Bhquvmkn8zLO36lGjuqk 2024-04-09 14:25:53 2024-04-09 14:25:56
|
|
|
- //59 1 6 ćé
243 ćé
èŸ
ć©çœćĄ bj http http://172.21.127.243:33128 molilian Bhquvmkn8zLO36lGjuqk 2024-04-09 14:25:53 2024-04-09 14:25:56
|
|
|
-
|
|
|
- foreach (var proxy in list)
|
|
|
- {
|
|
|
- //éèż curl myip.ipip.netæŁæ”proxyćŻèźżéźèĄ
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- var tasks = new List<Task<int>>
|
|
|
- {
|
|
|
- Task.Run(()=>{ })
|
|
|
- };
|
|
|
-
|
|
|
- // çćŸ
ææä»»ćĄćźæ
|
|
|
- Task.WhenAll(tasks).Wait();
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- return new APIResult(new { list });
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- [HttpGet]
|
|
|
- public async Task<ActionResult> ChangePublicIpByName(string nodeName)
|
|
|
- {
|
|
|
-
|
|
|
- var proxy_node = new DBContext.Table("proxy_nodes").Get<dynamic>("name=@nodeName", new { nodeName });
|
|
|
- if (proxy_node == null) return new APIResult(new { success = false, msg = "æČĄæćčé
ç proxy_nodes èź°ćœ" });
|
|
|
-
|
|
|
- int aliyun_id = proxy_node.aliyun_id;
|
|
|
- string proxy_server = proxy_node.server;
|
|
|
-
|
|
|
- var account = new DBContext.Table("aliyun_pool").Get<AliyunPoolDTO>(aliyun_id);
|
|
|
- if (account == null) return new APIResult(new { success = false, msg = "æČĄæćčé
ç aliyun_pool èź°ćœ" });
|
|
|
-
|
|
|
-
|
|
|
- var uri = new Uri(proxy_server);
|
|
|
- string privateIp = uri.Host;
|
|
|
- AliyunCore core = new AliyunCore(account);
|
|
|
- var success = await core.ChangePublicIpAsync(privateIp);
|
|
|
- return new APIResult(new { success = "ok" });
|
|
|
- }
|
|
|
-
|
|
|
- [HttpGet]
|
|
|
- public async Task<ActionResult> ChangePublicIp(int id)
|
|
|
- {
|
|
|
- id = id >= 20000 ? id - 20000 : id;
|
|
|
-
|
|
|
- var proxy_node = new DBContext.Table("proxy_nodes").Get<dynamic>(id);
|
|
|
- if (proxy_node == null) return new APIResult(new { success = false, msg = "æČĄæćčé
ç proxy_nodes èź°ćœ" });
|
|
|
-
|
|
|
- int aliyun_id = proxy_node.aliyun_id;
|
|
|
- string proxy_server = proxy_node.server;
|
|
|
-
|
|
|
- var account = new DBContext.Table("aliyun_pool").Get<AliyunPoolDTO>(aliyun_id);
|
|
|
- if (account == null) return new APIResult(new { success = false, msg = "æČĄæćčé
ç aliyun_pool èź°ćœ" });
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- var uri = new Uri(proxy_server);
|
|
|
- string privateIp = uri.Host;
|
|
|
- AliyunCore core = new AliyunCore(account);
|
|
|
- var success = await core.ChangePublicIpAsync(privateIp);
|
|
|
- return new APIResult(new { success = "ok" });
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
-}
|
|
|
+using dodohold.core;
|
|
|
+using Microsoft.AspNetCore.Mvc;
|
|
|
+using molilian.core;
|
|
|
+using System.Net;
|
|
|
+using System.Text.Json;
|
|
|
+
|
|
|
+namespace molilian.api.Controllers
|
|
|
+{
|
|
|
+ [ApiController]
|
|
|
+ [MyAuthorize("admin")]
|
|
|
+ [Route("api/[controller]/[action]")]
|
|
|
+ public class ProxyController : ControllerBase
|
|
|
+ {
|
|
|
+ private const string ProxyCheckRequestUrl = "http://cip.cc";
|
|
|
+ private const string ProxyCheckUserAgent = "curl/8.7.1";
|
|
|
+
|
|
|
+ readonly IAuthorizationProvider provider = new AdminProvider();
|
|
|
+ protected IHttpContextAccessor _accessor;
|
|
|
+
|
|
|
+ public ProxyController(IHttpContextAccessor accessor)
|
|
|
+ {
|
|
|
+ _accessor = accessor;
|
|
|
+ }
|
|
|
+
|
|
|
+ [HttpGet]
|
|
|
+ public ActionResult get()
|
|
|
+ {
|
|
|
+ return new APIResult(new
|
|
|
+ {
|
|
|
+ data = BuildProxyNodeListResult(1, 20, true, string.Empty, string.Empty)
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ [HttpPost]
|
|
|
+ public ActionResult list([FromBody] JsonElement form)
|
|
|
+ {
|
|
|
+ int page = form.Read("current", 1);
|
|
|
+ int size = form.Read("pageSize", 20);
|
|
|
+ bool getTotal = form.Read("getTotal", true);
|
|
|
+ string keyword = form.Read("keyword", string.Empty);
|
|
|
+ string status = form.Read("status", string.Empty);
|
|
|
+
|
|
|
+ return new APIResult(new
|
|
|
+ {
|
|
|
+ data = BuildProxyNodeListResult(page, size, getTotal, keyword, status)
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ private static dynamic BuildProxyNodeListResult(
|
|
|
+ int page,
|
|
|
+ int size,
|
|
|
+ bool getTotal,
|
|
|
+ string keyword,
|
|
|
+ string status
|
|
|
+ )
|
|
|
+ {
|
|
|
+ page = page <= 0 ? 1 : page;
|
|
|
+ size = size <= 0 ? 20 : size;
|
|
|
+
|
|
|
+ string filter = string.Empty;
|
|
|
+ string likeKeyword = string.Empty;
|
|
|
+ IEnumerable<string> matchedNodeNames = Array.Empty<string>();
|
|
|
+ bool? statusValue = null;
|
|
|
+
|
|
|
+ if (!string.IsNullOrWhiteSpace(status))
|
|
|
+ {
|
|
|
+ status = status.Trim().ToLowerInvariant();
|
|
|
+ if (status == "enabled")
|
|
|
+ {
|
|
|
+ statusValue = true;
|
|
|
+ filter += " AND status=@statusValue";
|
|
|
+ }
|
|
|
+ else if (status == "disabled")
|
|
|
+ {
|
|
|
+ statusValue = false;
|
|
|
+ filter += " AND status=@statusValue";
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!string.IsNullOrWhiteSpace(keyword))
|
|
|
+ {
|
|
|
+ likeKeyword = $"%{keyword.Trim()}%";
|
|
|
+ matchedNodeNames = FindMatchedNodeNames(likeKeyword).ToArray();
|
|
|
+
|
|
|
+ filter += " AND (name LIKE @likeKeyword OR nodeName LIKE @likeKeyword OR description LIKE @likeKeyword OR server LIKE @likeKeyword OR end_point LIKE @likeKeyword OR type LIKE @likeKeyword";
|
|
|
+ if (matchedNodeNames.Any())
|
|
|
+ {
|
|
|
+ filter += " OR name IN @matchedNodeNames OR nodeName IN @matchedNodeNames";
|
|
|
+ }
|
|
|
+ filter += ")";
|
|
|
+ }
|
|
|
+
|
|
|
+ filter = filter.StringTrimStart(" AND ");
|
|
|
+
|
|
|
+ var result = new DBContext.Table("proxy_nodes")
|
|
|
+ .Where(filter, new { statusValue, likeKeyword, matchedNodeNames })
|
|
|
+ .Page(size, page)
|
|
|
+ .Order("status DESC, name ASC")
|
|
|
+ .PageList<ProxyNodeListItemDTO>(getTotal);
|
|
|
+
|
|
|
+ List<ProxyNodeAccountSourceDTO> tkAccounts = LoadProxyNodeAccountSources("tk_pool");
|
|
|
+ List<ProxyNodeAccountSourceDTO> jdAccounts = LoadProxyNodeAccountSources("jd_pool");
|
|
|
+ List<ProxyNodeAccountSourceDTO> pddAccounts = LoadProxyNodeAccountSources("pdd_pool");
|
|
|
+
|
|
|
+ foreach (var node in result.List)
|
|
|
+ {
|
|
|
+ var accounts = BuildUsageAccounts(node, "tk", tkAccounts)
|
|
|
+ .Concat(BuildUsageAccounts(node, "jd", jdAccounts))
|
|
|
+ .Concat(BuildUsageAccounts(node, "pdd", pddAccounts))
|
|
|
+ .OrderByDescending(item => item.status)
|
|
|
+ .ThenBy(item => item.platform)
|
|
|
+ .ThenBy(item => item.name)
|
|
|
+ .ToList();
|
|
|
+
|
|
|
+ node.accountCount = accounts.Count;
|
|
|
+ node.onlineAccountCount = accounts.Count(item => item.status);
|
|
|
+ node.offlineAccountCount = accounts.Count(item => !item.status);
|
|
|
+ node.accounts = accounts;
|
|
|
+ }
|
|
|
+
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ [HttpPost]
|
|
|
+ public async Task<ActionResult> update([FromBody] JsonElement form)
|
|
|
+ {
|
|
|
+ var clientIp = _accessor.HttpContext.GetUserIp();
|
|
|
+ var token = provider.Get(_accessor.HttpContext);
|
|
|
+
|
|
|
+ int id = form.Read<int>("id", 0);
|
|
|
+ string name = form.Read<string>("name", string.Empty);
|
|
|
+ string val = form.Read<string>("val", string.Empty);
|
|
|
+
|
|
|
+ if (id == 0)
|
|
|
+ {
|
|
|
+ return new APIResult(new
|
|
|
+ {
|
|
|
+ data = new { success = false, msg = "æŽæ°ć€±èŽ„ïŒèŻ·æŁæ„èŸć
„ćæ°" }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ int result;
|
|
|
+ switch (name)
|
|
|
+ {
|
|
|
+ case "status":
|
|
|
+ bool bVal = "true".Equals(val, StringComparison.OrdinalIgnoreCase) || "1".Equals(val);
|
|
|
+ result = new DBContext.Table("proxy_nodes")
|
|
|
+ .Add(name, bVal)
|
|
|
+ .Add("last_time", DateTime.Now)
|
|
|
+ .Where("id=@id", new { id })
|
|
|
+ .Update();
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ return new APIResult(new
|
|
|
+ {
|
|
|
+ data = new { success = false, msg = "æŽæ°ć€±èŽ„ïŒæȘæææäœ" }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ bool success = result > 0;
|
|
|
+ if (success)
|
|
|
+ {
|
|
|
+ OperationLogCore.LogOperation(token.AccessKey, clientIp, $"proxy_nodes:{id}:{name}", string.Empty, val);
|
|
|
+ ProxyNodesCore.Refresh();
|
|
|
+ await EndPointCore.NotifyReload(true);
|
|
|
+ }
|
|
|
+
|
|
|
+ return new APIResult(new
|
|
|
+ {
|
|
|
+ data = new { success, msg = success ? "æŽæ°æć" : "æŽæ°ć€±èŽ„ïŒèŻ·æŁæ„èŸć
„俥æŻ" }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ [HttpGet]
|
|
|
+ public async Task<ActionResult> check(int id, string target = "internal")
|
|
|
+ {
|
|
|
+ var proxyNode = new DBContext.Table("proxy_nodes").Get<ProxyNodesDTO>("id=@id", new { id });
|
|
|
+ if (proxyNode == null)
|
|
|
+ {
|
|
|
+ return new APIResult(new
|
|
|
+ {
|
|
|
+ data = new { success = false, msg = "æČĄæćčé
ç proxy_nodes èź°ćœ" }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ target = string.IsNullOrWhiteSpace(target) ? "internal" : target.Trim().ToLowerInvariant();
|
|
|
+ if (target is not ("internal" or "external"))
|
|
|
+ {
|
|
|
+ return new APIResult(new
|
|
|
+ {
|
|
|
+ data = new { success = false, msg = "target ä»
æŻæ internal æ external" }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ string externalProxyAddress = BuildExternalProxyAddress(proxyNode.id);
|
|
|
+
|
|
|
+ var data = new ProxyNodeCheckResponseDTO
|
|
|
+ {
|
|
|
+ success = false,
|
|
|
+ msg = "æȘæ§èĄæŁæ”",
|
|
|
+ };
|
|
|
+
|
|
|
+ if (target == "internal")
|
|
|
+ {
|
|
|
+ var internalResult = await CheckProxyAsync(
|
|
|
+ proxyNode.server,
|
|
|
+ proxyNode.username,
|
|
|
+ proxyNode.password
|
|
|
+ );
|
|
|
+ data.success = internalResult.success;
|
|
|
+ data.msg = internalResult.success ? "ć
çœä»ŁçæŁæ”æć" : "ć
çœä»ŁçæŁæ”ć€±èŽ„";
|
|
|
+ data.check = new ProxyCheckChannelDTO
|
|
|
+ {
|
|
|
+ address = proxyNode.server,
|
|
|
+ success = internalResult.success,
|
|
|
+ result = internalResult.result,
|
|
|
+ };
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ var externalResult = await CheckProxyAsync(
|
|
|
+ BuildProxyUri(externalProxyAddress, proxyNode.type),
|
|
|
+ proxyNode.username,
|
|
|
+ proxyNode.password
|
|
|
+ );
|
|
|
+ data.success = externalResult.success;
|
|
|
+ data.msg = externalResult.success ? "ć€çœä»ŁçæŁæ”æć" : "ć€çœä»ŁçæŁæ”ć€±èŽ„";
|
|
|
+ data.check = new ProxyCheckChannelDTO
|
|
|
+ {
|
|
|
+ address = externalProxyAddress,
|
|
|
+ success = externalResult.success,
|
|
|
+ result = externalResult.result,
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
+ return new APIResult(new
|
|
|
+ {
|
|
|
+ data
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ [HttpGet]
|
|
|
+ public async Task<ActionResult> ChangePublicIpByName(string nodeName)
|
|
|
+ {
|
|
|
+ var proxyNode = new DBContext.Table("proxy_nodes")
|
|
|
+ .Get<dynamic>("(nodeName=@nodeName OR name=@nodeName)", new { nodeName });
|
|
|
+ if (proxyNode == null)
|
|
|
+ {
|
|
|
+ return new APIResult(new
|
|
|
+ {
|
|
|
+ data = new { success = false, msg = "æČĄæćčé
ç proxy_nodes èź°ćœ" }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ int aliyunId = proxyNode.aliyun_id;
|
|
|
+ string proxyServer = proxyNode.server;
|
|
|
+
|
|
|
+ var account = new DBContext.Table("aliyun_pool").Get<AliyunPoolDTO>(aliyunId);
|
|
|
+ if (account == null)
|
|
|
+ {
|
|
|
+ return new APIResult(new
|
|
|
+ {
|
|
|
+ data = new { success = false, msg = "æČĄæćčé
ç aliyun_pool èź°ćœ" }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ var uri = new Uri(proxyServer);
|
|
|
+ string privateIp = uri.Host;
|
|
|
+ AliyunCore core = new(account);
|
|
|
+ var (success, oldIp, newIp) = await core.ChangePublicIpAsync(privateIp);
|
|
|
+
|
|
|
+ return new APIResult(new
|
|
|
+ {
|
|
|
+ data = new
|
|
|
+ {
|
|
|
+ success,
|
|
|
+ msg = success ? $"æŽæąć
Źçœ IP æćïŒ{oldIp} -> {newIp}" : "æŽæąć
Źçœ IP ć€±èŽ„"
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ [HttpGet]
|
|
|
+ public async Task<ActionResult> ChangePublicIp(int id)
|
|
|
+ {
|
|
|
+ id = id >= 20000 ? id - 20000 : id;
|
|
|
+
|
|
|
+ var proxyNode = new DBContext.Table("proxy_nodes").Get<dynamic>(id);
|
|
|
+ if (proxyNode == null)
|
|
|
+ {
|
|
|
+ return new APIResult(new
|
|
|
+ {
|
|
|
+ data = new { success = false, msg = "æČĄæćčé
ç proxy_nodes èź°ćœ" }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ int aliyunId = proxyNode.aliyun_id;
|
|
|
+ string proxyServer = proxyNode.server;
|
|
|
+
|
|
|
+ var account = new DBContext.Table("aliyun_pool").Get<AliyunPoolDTO>(aliyunId);
|
|
|
+ if (account == null)
|
|
|
+ {
|
|
|
+ return new APIResult(new
|
|
|
+ {
|
|
|
+ data = new { success = false, msg = "æČĄæćčé
ç aliyun_pool èź°ćœ" }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ var uri = new Uri(proxyServer);
|
|
|
+ string privateIp = uri.Host;
|
|
|
+ AliyunCore core = new(account);
|
|
|
+ var (success, oldIp, newIp) = await core.ChangePublicIpAsync(privateIp);
|
|
|
+
|
|
|
+ return new APIResult(new
|
|
|
+ {
|
|
|
+ data = new
|
|
|
+ {
|
|
|
+ success,
|
|
|
+ msg = success ? $"æŽæąć
Źçœ IP æćïŒ{oldIp} -> {newIp}" : "æŽæąć
Źçœ IP ć€±èŽ„"
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ private static IEnumerable<ProxyNodeUsageAccountDTO> BuildUsageAccounts(
|
|
|
+ ProxyNodeListItemDTO node,
|
|
|
+ string platform,
|
|
|
+ IEnumerable<ProxyNodeAccountSourceDTO> accounts
|
|
|
+ )
|
|
|
+ {
|
|
|
+ var nodeNames = GetProxyNodeMatchNames(node).ToArray();
|
|
|
+ if (!nodeNames.Any())
|
|
|
+ {
|
|
|
+ return Enumerable.Empty<ProxyNodeUsageAccountDTO>();
|
|
|
+ }
|
|
|
+
|
|
|
+ return accounts
|
|
|
+ .Where(account => MatchNodeName(account.nodeName, nodeNames))
|
|
|
+ .Select(account => new ProxyNodeUsageAccountDTO
|
|
|
+ {
|
|
|
+ id = account.id,
|
|
|
+ platform = platform,
|
|
|
+ name = account.name,
|
|
|
+ company = account.company,
|
|
|
+ nodeName = account.nodeName,
|
|
|
+ status = account.status,
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ private static bool MatchNodeName(
|
|
|
+ string accountNodes,
|
|
|
+ IEnumerable<string> nodeNames
|
|
|
+ )
|
|
|
+ {
|
|
|
+ var nodeNameSet = nodeNames
|
|
|
+ .Where(item => !string.IsNullOrWhiteSpace(item))
|
|
|
+ .Select(item => item.Trim())
|
|
|
+ .ToHashSet(StringComparer.OrdinalIgnoreCase);
|
|
|
+
|
|
|
+ if (nodeNameSet.Count == 0)
|
|
|
+ {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ return SplitNodeNames(accountNodes)
|
|
|
+ .Any(item => nodeNameSet.Contains(item));
|
|
|
+ }
|
|
|
+
|
|
|
+ private static IEnumerable<string> GetProxyNodeMatchNames(ProxyNodeListItemDTO node)
|
|
|
+ {
|
|
|
+ return new[] { node.nodeName, node.name }
|
|
|
+ .Where(item => !string.IsNullOrWhiteSpace(item))
|
|
|
+ .Select(item => item.Trim())
|
|
|
+ .Distinct(StringComparer.OrdinalIgnoreCase);
|
|
|
+ }
|
|
|
+
|
|
|
+ private static IEnumerable<string> FindMatchedNodeNames(string keyword)
|
|
|
+ {
|
|
|
+ if (string.IsNullOrWhiteSpace(keyword))
|
|
|
+ {
|
|
|
+ return Array.Empty<string>();
|
|
|
+ }
|
|
|
+
|
|
|
+ const string accountFilter = "name LIKE @keyword OR company LIKE @keyword OR nodename LIKE @keyword";
|
|
|
+
|
|
|
+ List<ProxyNodeNameSourceDTO> allNodes = new();
|
|
|
+ allNodes.AddRange(LoadProxyNodeNameSources("tk_pool", accountFilter, keyword));
|
|
|
+ allNodes.AddRange(LoadProxyNodeNameSources("jd_pool", accountFilter, keyword));
|
|
|
+ allNodes.AddRange(LoadProxyNodeNameSources("pdd_pool", accountFilter, keyword));
|
|
|
+
|
|
|
+ return allNodes
|
|
|
+ .SelectMany(item => SplitNodeNames(item.nodeName))
|
|
|
+ .Distinct(StringComparer.OrdinalIgnoreCase)
|
|
|
+ .ToList();
|
|
|
+ }
|
|
|
+
|
|
|
+ private static List<ProxyNodeAccountSourceDTO> LoadProxyNodeAccountSources(string tableName)
|
|
|
+ {
|
|
|
+ return new DBContext.Table(tableName)
|
|
|
+ .Fields("id, name, company, status, nodename AS nodeName")
|
|
|
+ .Select<ProxyNodeAccountSourceDTO>()?
|
|
|
+ .ToList() ?? new List<ProxyNodeAccountSourceDTO>();
|
|
|
+ }
|
|
|
+
|
|
|
+ private static List<ProxyNodeNameSourceDTO> LoadProxyNodeNameSources(
|
|
|
+ string tableName,
|
|
|
+ string filter,
|
|
|
+ string keyword
|
|
|
+ )
|
|
|
+ {
|
|
|
+ return new DBContext.Table(tableName)
|
|
|
+ .Fields("nodename AS nodeName")
|
|
|
+ .Where(filter, new { keyword })
|
|
|
+ .Select<ProxyNodeNameSourceDTO>()?
|
|
|
+ .ToList() ?? new List<ProxyNodeNameSourceDTO>();
|
|
|
+ }
|
|
|
+
|
|
|
+ private static IEnumerable<string> SplitNodeNames(string accountNodes)
|
|
|
+ {
|
|
|
+ if (string.IsNullOrWhiteSpace(accountNodes))
|
|
|
+ {
|
|
|
+ return Array.Empty<string>();
|
|
|
+ }
|
|
|
+
|
|
|
+ return accountNodes
|
|
|
+ .Replace('ïŒ', ',')
|
|
|
+ .Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
|
|
|
+ }
|
|
|
+
|
|
|
+ private static string BuildExternalProxyAddress(int id)
|
|
|
+ {
|
|
|
+ return $"bjapi.molilian.com:20{id:D3}";
|
|
|
+ }
|
|
|
+
|
|
|
+ private static string BuildProxyUri(string address, string type)
|
|
|
+ {
|
|
|
+ if (string.IsNullOrWhiteSpace(address))
|
|
|
+ {
|
|
|
+ return string.Empty;
|
|
|
+ }
|
|
|
+
|
|
|
+ address = address.Trim();
|
|
|
+ if (address.Contains("://", StringComparison.Ordinal) &&
|
|
|
+ Uri.TryCreate(address, UriKind.Absolute, out var absoluteUri))
|
|
|
+ {
|
|
|
+ return absoluteUri.AbsoluteUri;
|
|
|
+ }
|
|
|
+
|
|
|
+ string scheme = string.IsNullOrWhiteSpace(type) ? "http" : type.Trim().ToLowerInvariant();
|
|
|
+ if (scheme is not ("http" or "https" or "socks4" or "socks4a" or "socks5"))
|
|
|
+ {
|
|
|
+ scheme = "http";
|
|
|
+ }
|
|
|
+ return $"{scheme}://{address}";
|
|
|
+ }
|
|
|
+
|
|
|
+ private static async Task<(bool success, string result)> CheckProxyAsync(
|
|
|
+ string proxyAddress,
|
|
|
+ string username,
|
|
|
+ string password
|
|
|
+ )
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ string proxyUri = BuildProxyUri(proxyAddress, "http");
|
|
|
+ WebClientUtility client = new()
|
|
|
+ {
|
|
|
+ Timeout = TimeSpan.FromSeconds(3),
|
|
|
+ UserAgent = ProxyCheckUserAgent,
|
|
|
+ };
|
|
|
+
|
|
|
+ if (string.IsNullOrWhiteSpace(proxyUri))
|
|
|
+ {
|
|
|
+ return (false, "代çć°ćäžșç©ș");
|
|
|
+ }
|
|
|
+
|
|
|
+ client.Proxy = new WebProxy
|
|
|
+ {
|
|
|
+ Address = new Uri(proxyUri),
|
|
|
+ Credentials = string.IsNullOrWhiteSpace(username) && string.IsNullOrWhiteSpace(password)
|
|
|
+ ? null
|
|
|
+ : new NetworkCredential(username, password)
|
|
|
+ };
|
|
|
+
|
|
|
+ var response = await client.RequestAsync(ProxyCheckRequestUrl);
|
|
|
+ string body = response.Body()?.Trim() ?? string.Empty;
|
|
|
+
|
|
|
+ if (response.Successed)
|
|
|
+ {
|
|
|
+ return (true, string.IsNullOrWhiteSpace(body) ? "代çćŻçšïŒäœçźæ ç«çčæ èżćć
ćźč" : body);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (response.ResponseException != null)
|
|
|
+ {
|
|
|
+ return (false, response.ResponseException.GetBaseException().Message);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (response.ResponseMessage != null)
|
|
|
+ {
|
|
|
+ string message = $"HTTP {(int)response.ResponseMessage.StatusCode}";
|
|
|
+ if (!string.IsNullOrWhiteSpace(body))
|
|
|
+ {
|
|
|
+ message += $" - {body}";
|
|
|
+ }
|
|
|
+ return (false, message);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!string.IsNullOrWhiteSpace(body))
|
|
|
+ {
|
|
|
+ return (false, body);
|
|
|
+ }
|
|
|
+
|
|
|
+ return (false, "èŻ·æ±ć€±èŽ„ïŒäœæȘèżććŒćžžæććșć
ćźč");
|
|
|
+ }
|
|
|
+ catch (TaskCanceledException)
|
|
|
+ {
|
|
|
+ return (false, "èŻ·æ±è¶
æ¶ïŒ3sïŒ");
|
|
|
+ }
|
|
|
+ catch (Exception ex)
|
|
|
+ {
|
|
|
+ return (false, ex.GetBaseException().Message);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public class ProxyNodeAccountSourceDTO
|
|
|
+ {
|
|
|
+ public int id { get; set; }
|
|
|
+ public string name { get; set; } = string.Empty;
|
|
|
+ public string company { get; set; } = string.Empty;
|
|
|
+ public bool status { get; set; }
|
|
|
+ public string nodeName { get; set; } = string.Empty;
|
|
|
+ }
|
|
|
+
|
|
|
+ public class ProxyNodeNameSourceDTO
|
|
|
+ {
|
|
|
+ public string nodeName { get; set; } = string.Empty;
|
|
|
+ }
|
|
|
+
|
|
|
+ public class ProxyNodeUsageAccountDTO
|
|
|
+ {
|
|
|
+ public int id { get; set; }
|
|
|
+ public string platform { get; set; } = string.Empty;
|
|
|
+ public string name { get; set; } = string.Empty;
|
|
|
+ public string company { get; set; } = string.Empty;
|
|
|
+ public string nodeName { get; set; } = string.Empty;
|
|
|
+ public bool status { get; set; }
|
|
|
+ }
|
|
|
+
|
|
|
+ public class ProxyNodeListItemDTO
|
|
|
+ {
|
|
|
+ public int id { get; set; }
|
|
|
+ public bool status { get; set; }
|
|
|
+ public string name { get; set; } = string.Empty;
|
|
|
+ public string nodeName { get; set; } = string.Empty;
|
|
|
+ public string description { get; set; } = string.Empty;
|
|
|
+ public string end_point { get; set; } = string.Empty;
|
|
|
+ public string type { get; set; } = string.Empty;
|
|
|
+ public string server { get; set; } = string.Empty;
|
|
|
+ public string username { get; set; } = string.Empty;
|
|
|
+ public DateTime create_time { get; set; }
|
|
|
+ public DateTime last_time { get; set; }
|
|
|
+ public int accountCount { get; set; }
|
|
|
+ public int onlineAccountCount { get; set; }
|
|
|
+ public int offlineAccountCount { get; set; }
|
|
|
+ public List<ProxyNodeUsageAccountDTO> accounts { get; set; } = new();
|
|
|
+ }
|
|
|
+
|
|
|
+ public class ProxyCheckChannelDTO
|
|
|
+ {
|
|
|
+ public string address { get; set; } = string.Empty;
|
|
|
+ public bool success { get; set; }
|
|
|
+ public string result { get; set; } = string.Empty;
|
|
|
+ }
|
|
|
+
|
|
|
+ public class ProxyNodeCheckResponseDTO
|
|
|
+ {
|
|
|
+ public bool success { get; set; }
|
|
|
+ public string msg { get; set; } = string.Empty;
|
|
|
+ public ProxyCheckChannelDTO? check { get; set; }
|
|
|
+ }
|
|
|
+}
|