|
@@ -170,14 +170,47 @@ namespace molilian.core
|
|
|
/// </summary>
|
|
/// </summary>
|
|
|
/// <param name="url"></param>
|
|
/// <param name="url"></param>
|
|
|
/// <returns></returns>
|
|
/// <returns></returns>
|
|
|
- public async Task<(bool, string)> GetDesiredUrlAsync(WebProxy proxy, string url, CancellationToken cancellationToken = default)
|
|
|
|
|
- {
|
|
|
|
|
- string result;
|
|
|
|
|
- try
|
|
|
|
|
- {
|
|
|
|
|
- if (!IsShortLink(url)) return (false, "不是淘宝短网址");
|
|
|
|
|
-
|
|
|
|
|
- if (!_account.enable_deep_url) return (true, url);
|
|
|
|
|
|
|
+ public async Task<(bool, string)> GetDesiredUrlAsync(WebProxy proxy, string url, CancellationToken cancellationToken = default)
|
|
|
|
|
+ {
|
|
|
|
|
+ var result = await GetDesiredUrlResultAsync(proxy, url, cancellationToken);
|
|
|
|
|
+ return (result.Success, result.Content);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private readonly record struct DesiredUrlResult(bool Success, string Content, bool UsedGeneralLinkParse);
|
|
|
|
|
+
|
|
|
|
|
+ private async Task<DesiredUrlResult> GetDesiredUrlResultAsync(WebProxy proxy, string url, CancellationToken cancellationToken)
|
|
|
|
|
+ {
|
|
|
|
|
+ string result;
|
|
|
|
|
+ bool usedGeneralLinkParse = false;
|
|
|
|
|
+ try
|
|
|
|
|
+ {
|
|
|
|
|
+ if (!IsShortLink(url)) return new(false, "不是淘宝短网址", false);
|
|
|
|
|
+
|
|
|
|
|
+ if (_account.use_general_link_parse_pool)
|
|
|
|
|
+ {
|
|
|
|
|
+ usedGeneralLinkParse = true;
|
|
|
|
|
+ var parsed = await endpoint_tbk_dg_general_link_parse(url, new TkDataDTO { content = url }, cancellationToken);
|
|
|
|
|
+ if (parsed.subCode != TkSubCodeEnum.GeneralLinkParsePoolUnavailable)
|
|
|
|
|
+ {
|
|
|
|
|
+ if (!parsed.success) return new(false, parsed.reason, true);
|
|
|
|
|
+
|
|
|
|
|
+ string desiredUrl = IsDigitsOnly(parsed.itemId)
|
|
|
|
|
+ ? $"https://item.taobao.com/item.htm?id={parsed.itemId}"
|
|
|
|
|
+ : parsed.item_url;
|
|
|
|
|
+ return new(true, desiredUrl, true);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 账号池无可用账号时,继续按下探网址设置执行原逻辑。
|
|
|
|
|
+ usedGeneralLinkParse = false;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ cancellationToken.ThrowIfCancellationRequested();
|
|
|
|
|
+ if (!_account.enable_deep_url) return new(true, url, false);
|
|
|
|
|
+
|
|
|
|
|
+ if (_account.use_general_link_parse_pool)
|
|
|
|
|
+ {
|
|
|
|
|
+ proxy ??= ProxyNodesCore.RandomOne(_account.nodeName);
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
string desiredUrlPattern = "var url = '(.*?)'";
|
|
string desiredUrlPattern = "var url = '(.*?)'";
|
|
|
WebClientUtility client = new()
|
|
WebClientUtility client = new()
|
|
@@ -202,8 +235,8 @@ namespace molilian.core
|
|
|
if (response.ResponseMessage?.StatusCode == HttpStatusCode.Found &&
|
|
if (response.ResponseMessage?.StatusCode == HttpStatusCode.Found &&
|
|
|
!string.IsNullOrEmpty(response.ResponseMessage?.Headers?.Location?.OriginalString))
|
|
!string.IsNullOrEmpty(response.ResponseMessage?.Headers?.Location?.OriginalString))
|
|
|
{
|
|
{
|
|
|
- string redirectUrl = response.ResponseMessage?.Headers?.Location?.OriginalString;
|
|
|
|
|
- return (true, redirectUrl);
|
|
|
|
|
|
|
+ string redirectUrl = response.ResponseMessage?.Headers?.Location?.OriginalString;
|
|
|
|
|
+ return new(true, redirectUrl, false);
|
|
|
}
|
|
}
|
|
|
var responseBody = response.Body();
|
|
var responseBody = response.Body();
|
|
|
result = responseBody;
|
|
result = responseBody;
|
|
@@ -217,10 +250,10 @@ namespace molilian.core
|
|
|
{
|
|
{
|
|
|
result = match.Groups[1].Value; // 返回匹配的 URL
|
|
result = match.Groups[1].Value; // 返回匹配的 URL
|
|
|
|
|
|
|
|
- if (string.IsNullOrEmpty(result)) return (false, "没有匹配的URL");
|
|
|
|
|
|
|
+ if (string.IsNullOrEmpty(result)) return new(false, "没有匹配的URL", false);
|
|
|
if (result.StartsWith("//"))
|
|
if (result.StartsWith("//"))
|
|
|
result = "https:" + result;
|
|
result = "https:" + result;
|
|
|
- return (true, result);
|
|
|
|
|
|
|
+ return new(true, result, false);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
else
|
|
else
|
|
@@ -234,12 +267,16 @@ namespace molilian.core
|
|
|
|
|
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
- catch (Exception ex)
|
|
|
|
|
- {
|
|
|
|
|
- _ = new LoggerLibrary("api_error", "desiredUrl_error").Info(ex.Message, ex.StackTrace).SaveAsync();
|
|
|
|
|
|
|
+ catch (OperationCanceledException) when (cancellationToken.IsCancellationRequested)
|
|
|
|
|
+ {
|
|
|
|
|
+ throw;
|
|
|
|
|
+ }
|
|
|
|
|
+ catch (Exception ex)
|
|
|
|
|
+ {
|
|
|
|
|
+ _ = new LoggerLibrary("api_error", "desiredUrl_error").Info(ex.Message, ex.StackTrace).SaveAsync();
|
|
|
result = "网络异常";
|
|
result = "网络异常";
|
|
|
}
|
|
}
|
|
|
- return (false, result);
|
|
|
|
|
|
|
+ return new(false, result, usedGeneralLinkParse);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
/// <summary>
|
|
@@ -455,10 +492,9 @@ namespace molilian.core
|
|
|
result.shortLinkurl = null;
|
|
result.shortLinkurl = null;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- public async Task<TkDataDTO> InternalTextProcessingAsync(string content, TkDataDTO result,
|
|
|
|
|
- CancellationToken cancellationToken = default,
|
|
|
|
|
- Dictionary<string, long> swData = null,
|
|
|
|
|
- bool preserveShortLinks = false)
|
|
|
|
|
|
|
+ public async Task<TkDataDTO> InternalTextProcessingAsync(string content, TkDataDTO result,
|
|
|
|
|
+ CancellationToken cancellationToken = default,
|
|
|
|
|
+ Dictionary<string, long> swData = null)
|
|
|
{
|
|
{
|
|
|
bool success;
|
|
bool success;
|
|
|
string resultText;
|
|
string resultText;
|
|
@@ -493,30 +529,32 @@ namespace molilian.core
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
- if (preserveShortLinks && IsShortLink(url))
|
|
|
|
|
- {
|
|
|
|
|
- result.success = false;
|
|
|
|
|
- result.message = string.Empty;
|
|
|
|
|
- result.reason = string.Empty;
|
|
|
|
|
- result.content = content;
|
|
|
|
|
- result.link_type = LinkTypeEnum.baseDomain;
|
|
|
|
|
- result.elapsedTime2 = 0;
|
|
|
|
|
- return result;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- Stopwatch sw = Stopwatch.StartNew();
|
|
|
|
|
-
|
|
|
|
|
- var proxy = ProxyNodesCore.RandomOne(_account.nodeName);
|
|
|
|
|
|
|
+ Stopwatch sw = Stopwatch.StartNew();
|
|
|
|
|
+
|
|
|
|
|
+ var proxy = _account.use_general_link_parse_pool ? null : ProxyNodesCore.RandomOne(_account.nodeName);
|
|
|
if (_proxy != null && proxy != null && _proxy.Address != proxy.Address)
|
|
if (_proxy != null && proxy != null && _proxy.Address != proxy.Address)
|
|
|
{
|
|
{
|
|
|
result.proxy_node = proxy?.Address?.Authority;
|
|
result.proxy_node = proxy?.Address?.Authority;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- (success, resultText) = await GetDesiredUrlAsync(proxy, url, cancellationToken);
|
|
|
|
|
|
|
+ var desiredUrlResult = await GetDesiredUrlResultAsync(proxy, url, cancellationToken);
|
|
|
|
|
+ success = desiredUrlResult.Success;
|
|
|
|
|
+ resultText = desiredUrlResult.Content;
|
|
|
sw.Stop();
|
|
sw.Stop();
|
|
|
// 获取执行时间
|
|
// 获取执行时间
|
|
|
- result.elapsedTime2 = (int)sw.ElapsedMilliseconds;
|
|
|
|
|
- swData?.Add("\tGetDesiredUrlAsync", sw.ElapsedMilliseconds);
|
|
|
|
|
|
|
+ result.elapsedTime2 = (int)sw.ElapsedMilliseconds;
|
|
|
|
|
+ swData?.Add("\tGetDesiredUrlAsync", sw.ElapsedMilliseconds);
|
|
|
|
|
+
|
|
|
|
|
+ if (desiredUrlResult.UsedGeneralLinkParse && !success)
|
|
|
|
|
+ {
|
|
|
|
|
+ result.success = false;
|
|
|
|
|
+ result.message = "解析失败";
|
|
|
|
|
+ result.reason = resultText;
|
|
|
|
|
+ result.subCode = TkSubCodeEnum.NoConvert;
|
|
|
|
|
+ result.link_type = LinkTypeEnum.unknown;
|
|
|
|
|
+ result.content = content;
|
|
|
|
|
+ return result;
|
|
|
|
|
+ }
|
|
|
//============================== 放弃转链-请求超时 ==============================
|
|
//============================== 放弃转链-请求超时 ==============================
|
|
|
#if DEBUG
|
|
#if DEBUG
|
|
|
#else
|
|
#else
|