-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
424 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,252 @@ | ||
using System.IO.Compression; | ||
using System.Net; | ||
using System.Text; | ||
using System.Text.RegularExpressions; | ||
|
||
namespace KCNLanzouDirectLink | ||
{ | ||
internal static class GetUrlHelper | ||
{ | ||
/// <summary> | ||
/// 获取直链 | ||
/// </summary> | ||
/// <param name="url"></param> | ||
/// <returns></returns> | ||
public static async Task<string?> GetFullUrl(string url) | ||
{ | ||
return await GetFinalUrlAsync( | ||
ExtractAndCombineLinks( | ||
await GetHtmlContentAsync(url))); | ||
} | ||
|
||
/// <summary> | ||
/// 获取直链(加密) | ||
/// </summary> | ||
/// <param name="url"></param> | ||
/// <param name="key"></param> | ||
/// <returns></returns> | ||
public static async Task<string?> GetFullUrl(string url, string key) | ||
{ | ||
var postsign = ExtractPatternValue( | ||
await GetHtmlContentAsync(url), | ||
@"var\s*vidksek\s*=\s*['""]([^'""]+)['""]"); | ||
return await GetFinalUrlToPassAsync(await GetHtmlToPassContentAsync(postsign, key)); | ||
} | ||
|
||
/// <summary> | ||
/// 模拟浏览器请求Html | ||
/// </summary> | ||
/// <param name="url"></param> | ||
/// <returns></returns> | ||
public static async Task<string?> GetHtmlContentAsync(string? url) | ||
{ | ||
if (url == null) | ||
return null; | ||
|
||
using HttpClient client = new HttpClient(); | ||
client.DefaultRequestHeaders.Clear(); | ||
client.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (iPhone; CPU iPhone OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A5376e Safari/8536.25"); | ||
client.DefaultRequestHeaders.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8"); | ||
client.DefaultRequestHeaders.Add("Accept-Encoding", "gzip, deflate"); | ||
client.DefaultRequestHeaders.Add("Accept-Language", "zh-CN,zh;q=0.9"); | ||
client.DefaultRequestHeaders.Add("Cache-Control", "no-cache"); | ||
client.DefaultRequestHeaders.Add("Connection", "keep-alive"); | ||
client.DefaultRequestHeaders.Add("Pragma", "no-cache"); | ||
client.DefaultRequestHeaders.Add("Upgrade-Insecure-Requests", "1"); | ||
|
||
url = ModifyUrlForTp(url); | ||
HttpResponseMessage response = await client.GetAsync(url); | ||
response.EnsureSuccessStatusCode(); | ||
|
||
string contentEncoding = response.Content.Headers.ContentEncoding.ToString(); | ||
|
||
byte[] responseBytes = await response.Content.ReadAsByteArrayAsync(); | ||
return contentEncoding.Contains("gzip", StringComparison.OrdinalIgnoreCase) | ||
? DecompressGzip(responseBytes) | ||
: Encoding.UTF8.GetString(responseBytes); | ||
} | ||
|
||
/// <summary> | ||
/// 模拟浏览器请求Html(加密) | ||
/// </summary> | ||
/// <param name="url"></param> | ||
/// <returns></returns> | ||
public static async Task<string?> GetHtmlToPassContentAsync(string postsign, string key) | ||
{ | ||
using HttpClient client = new HttpClient(); | ||
client.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (iPhone; CPU iPhone OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A5376e Safari/8536.25"); | ||
client.DefaultRequestHeaders.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8"); | ||
client.DefaultRequestHeaders.Add("Accept-Encoding", "gzip, deflate"); | ||
client.DefaultRequestHeaders.Add("Accept-Language", "zh-CN,zh;q=0.9"); | ||
client.DefaultRequestHeaders.Add("Cache-Control", "no-cache"); | ||
client.DefaultRequestHeaders.Add("Connection", "keep-alive"); | ||
client.DefaultRequestHeaders.Add("Pragma", "no-cache"); | ||
client.DefaultRequestHeaders.Add("Upgrade-Insecure-Requests", "1"); | ||
client.DefaultRequestHeaders.Add("Referer", "https://syxz.lanzoue.com"); | ||
|
||
var postData = new StringContent($"action=downprocess&sign={postsign}&p={key}", Encoding.UTF8, "application/x-www-form-urlencoded"); | ||
var response = await client.PostAsync("https://syxz.lanzoue.com/ajaxm.php", postData); | ||
|
||
string content = await response.Content.ReadAsStringAsync(); | ||
|
||
var jsonResponse = Newtonsoft.Json.Linq.JObject.Parse(content); | ||
string? domain = jsonResponse["dom"]?.ToString(); | ||
string? url = jsonResponse["url"]?.ToString(); | ||
|
||
if (string.IsNullOrEmpty(domain) || string.IsNullOrEmpty(url)) | ||
return null; | ||
|
||
string fullDownloadUrl = BuildDownloadUrl(domain, url); | ||
return fullDownloadUrl; | ||
} | ||
|
||
/// <summary> | ||
/// 获取中间链接 | ||
/// </summary> | ||
/// <param name="htmlContent"></param> | ||
/// <returns></returns> | ||
public static string? ExtractAndCombineLinks(string? htmlContent) | ||
{ | ||
if (htmlContent == null) | ||
return null; | ||
|
||
var vkjxld = ExtractPatternValue(htmlContent, @"var\s*vkjxld\s*=\s*['""]([^'""]+)['""]"); | ||
var hyggid = ExtractPatternValue(htmlContent, @"var\s*hyggid\s*=\s*['""]([^'""]+)['""]"); | ||
|
||
if (vkjxld == null || hyggid == null) | ||
return null; | ||
|
||
return vkjxld + hyggid; | ||
} | ||
|
||
/// <summary> | ||
/// 获取最终直链 | ||
/// </summary> | ||
/// <param name="intermediateUrl"></param> | ||
/// <returns></returns> | ||
public static async Task<string?> GetFinalUrlAsync(string? intermediateUrl) | ||
{ | ||
if (string.IsNullOrEmpty(intermediateUrl)) | ||
return null; | ||
|
||
HttpClientHandler handler = new HttpClientHandler | ||
{ | ||
AllowAutoRedirect = false, | ||
}; | ||
|
||
using HttpClient client = new HttpClient(handler); | ||
client.DefaultRequestHeaders.Clear(); | ||
client.DefaultRequestHeaders.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7"); | ||
client.DefaultRequestHeaders.Add("Accept-Encoding", "gzip, deflate, br, zstd"); | ||
client.DefaultRequestHeaders.Add("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6"); | ||
client.DefaultRequestHeaders.Add("Connection", "keep-alive"); | ||
client.DefaultRequestHeaders.Add("Host", "slssq.osslan.com:446"); | ||
client.DefaultRequestHeaders.Add("Sec-CH-UA", "\"Chromium\";v=\"130\", \"Microsoft Edge\";v=\"130\", \"Not?A_Brand\";v=\"99\""); | ||
client.DefaultRequestHeaders.Add("Sec-CH-UA-Mobile", "?0"); | ||
client.DefaultRequestHeaders.Add("Sec-CH-UA-Platform", "\"Windows\""); | ||
client.DefaultRequestHeaders.Add("Sec-Fetch-Dest", "document"); | ||
client.DefaultRequestHeaders.Add("Sec-Fetch-Mode", "navigate"); | ||
client.DefaultRequestHeaders.Add("Sec-Fetch-Site", "none"); | ||
client.DefaultRequestHeaders.Add("Sec-Fetch-User", "?1"); | ||
client.DefaultRequestHeaders.Add("Upgrade-Insecure-Requests", "1"); | ||
client.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36 Edg/130.0.0.0"); | ||
|
||
HttpResponseMessage response = await client.GetAsync(intermediateUrl); | ||
|
||
if ((int)response.StatusCode < 300 || (int)response.StatusCode >= 400) | ||
return null; | ||
|
||
if (!response.Headers.Contains("Location")) | ||
return null; | ||
|
||
return response.Headers?.Location?.ToString(); | ||
} | ||
|
||
/// <summary> | ||
/// 获取最终直链(加密) | ||
/// </summary> | ||
/// <param name="intermediateUrl"></param> | ||
/// <returns></returns> | ||
public static async Task<string?> GetFinalUrlToPassAsync(string? intermediateUrl) | ||
{ | ||
if (string.IsNullOrEmpty(intermediateUrl)) | ||
return null; | ||
|
||
HttpClientHandler handler = new HttpClientHandler | ||
{ | ||
AllowAutoRedirect = false, | ||
}; | ||
|
||
using HttpClient client = new HttpClient(handler); | ||
client.DefaultRequestHeaders.Clear(); | ||
client.DefaultRequestHeaders.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7"); | ||
client.DefaultRequestHeaders.Add("Accept-Encoding", "gzip, deflate"); | ||
client.DefaultRequestHeaders.Add("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6"); | ||
client.DefaultRequestHeaders.Add("Host", "develope-oss.lanzouc.com"); | ||
client.DefaultRequestHeaders.Add("Proxy-Connection", "keep-alive"); | ||
client.DefaultRequestHeaders.Add("Upgrade-Insecure-Requests", "1"); | ||
client.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36 Edg/130.0.0.0"); | ||
|
||
HttpResponseMessage response = await client.GetAsync(intermediateUrl); | ||
|
||
if ((int)response.StatusCode < 300 || (int)response.StatusCode >= 400) | ||
return null; | ||
|
||
if (!response.Headers.Contains("Location")) | ||
return null; | ||
|
||
return response.Headers?.Location?.ToString(); | ||
} | ||
|
||
/// <summary> | ||
/// 正则提取html值 | ||
/// </summary> | ||
/// <param name="htmlContent"></param> | ||
/// <param name="pattern"></param> | ||
/// <returns></returns> | ||
private static string? ExtractPatternValue(string htmlContent, string pattern) | ||
{ | ||
var regex = new Regex(pattern, RegexOptions.Compiled); | ||
var match = regex.Match(htmlContent); | ||
return match.Success ? match.Groups[1].Value : null; | ||
} | ||
|
||
/// <summary> | ||
/// 格式化Url | ||
/// </summary> | ||
/// <param name="url"></param> | ||
/// <returns></returns> | ||
public static string ModifyUrlForTp(string url) | ||
{ | ||
int lastSlashIndex = url.LastIndexOf('/'); | ||
if (lastSlashIndex == -1) | ||
return url; | ||
return url.Substring(0, lastSlashIndex + 1) + "tp/" + url.Substring(lastSlashIndex + 1); | ||
} | ||
|
||
/// <summary> | ||
/// 格式化加密Url | ||
/// </summary> | ||
/// <param name="domain"></param> | ||
/// <param name="url"></param> | ||
/// <returns></returns> | ||
public static string BuildDownloadUrl(string domain, string url) | ||
{ | ||
string fullUrl = domain + "/file/" + WebUtility.UrlDecode(url); | ||
return fullUrl; | ||
} | ||
|
||
/// <summary> | ||
/// 解压Gzip数据 | ||
/// </summary> | ||
/// <param name="gzipData"></param> | ||
/// <returns></returns> | ||
private static string DecompressGzip(byte[] gzipData) | ||
{ | ||
using var ms = new MemoryStream(gzipData); | ||
using var gzipStream = new GZipStream(ms, CompressionMode.Decompress); | ||
using var reader = new StreamReader(gzipStream, Encoding.UTF8); | ||
return reader.ReadToEnd(); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<TargetFrameworks>net6.0;net7.0;net8.0;</TargetFrameworks> | ||
<ImplicitUsings>enable</ImplicitUsings> | ||
<!-- | ||
<Nullable>enable</Nullable> | ||
--> | ||
|
||
<!-- NuGet --> | ||
<PackageId>KCNLanzouDirectLink</PackageId> | ||
<Version>1.0.0</Version> | ||
<Authors>剧毒的KCN(JDDKCN)</Authors> | ||
<Company>KCN-Server</Company> | ||
<Description>用于解析蓝奏云直链的C#原生实现类库。</Description> | ||
|
||
<!-- 标签 --> | ||
<PackageTags>Lanzou;DirectLink;Cloud;Download</PackageTags> | ||
|
||
<!-- 许可证 --> | ||
<PackageLicenseExpression>AGPL-3.0-or-later</PackageLicenseExpression> | ||
|
||
<!-- 项目源 --> | ||
<RepositoryUrl>https://github.com/JDDKCN/KCNLanzouDirectLink</RepositoryUrl> | ||
|
||
<!-- 发布配置 --> | ||
<Configuration>Release</Configuration> | ||
<GeneratePackageOnBuild>True</GeneratePackageOnBuild> | ||
<Title>KCNLanzouDirectLink</Title> | ||
<Copyright>Copyright ©2023-2024 剧毒的KCN, All Rights Reserved.</Copyright> | ||
<PackageProjectUrl>https://github.com/JDDKCN/KCNLanzouDirectLink</PackageProjectUrl> | ||
<PackageRequireLicenseAcceptance>True</PackageRequireLicenseAcceptance> | ||
<PackageReleaseNotes>初次发布</PackageReleaseNotes> | ||
<PackageReadmeFile>Readme.md</PackageReadmeFile> | ||
<PackageIcon>favicon.png</PackageIcon> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<None Include="favicon.png" Pack="true" PackagePath="\" /> | ||
<None Include="Readme.md" Pack="true" PackagePath="\" /> | ||
</ItemGroup> | ||
|
||
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
|
||
Microsoft Visual Studio Solution File, Format Version 12.00 | ||
# Visual Studio Version 17 | ||
VisualStudioVersion = 17.9.34728.123 | ||
MinimumVisualStudioVersion = 10.0.40219.1 | ||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KCNLanzouDirectLink", "KCNLanzouDirectLink.csproj", "{B6774CDE-57D3-4B33-984D-23BF0B6BE6BE}" | ||
EndProject | ||
Global | ||
GlobalSection(SolutionConfigurationPlatforms) = preSolution | ||
Debug|Any CPU = Debug|Any CPU | ||
Release|Any CPU = Release|Any CPU | ||
EndGlobalSection | ||
GlobalSection(ProjectConfigurationPlatforms) = postSolution | ||
{B6774CDE-57D3-4B33-984D-23BF0B6BE6BE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||
{B6774CDE-57D3-4B33-984D-23BF0B6BE6BE}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||
{B6774CDE-57D3-4B33-984D-23BF0B6BE6BE}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||
{B6774CDE-57D3-4B33-984D-23BF0B6BE6BE}.Release|Any CPU.Build.0 = Release|Any CPU | ||
EndGlobalSection | ||
GlobalSection(SolutionProperties) = preSolution | ||
HideSolutionNode = FALSE | ||
EndGlobalSection | ||
GlobalSection(ExtensibilityGlobals) = postSolution | ||
SolutionGuid = {26E69CBA-8EC2-4A57-80C2-62D3E652E325} | ||
EndGlobalSection | ||
EndGlobal |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
namespace KCNLanzouDirectLink | ||
{ | ||
/// <summary> | ||
/// 解析蓝奏云直链 | ||
/// </summary> | ||
public static class KCNLanzouLinkHelper | ||
{ | ||
/// <summary> | ||
/// 获取蓝奏云分享链接的直链。 | ||
/// </summary> | ||
/// <param name="url">蓝奏云分享链接</param> | ||
/// <returns>返回解析后的直链,若失败则返回 null</returns> | ||
public static async Task<string?> GetDirectLinkAsync(string url) | ||
{ | ||
return await GetUrlHelper.GetFullUrl(url); | ||
} | ||
|
||
/// <summary> | ||
/// 获取加密蓝奏云分享链接的直链。 | ||
/// </summary> | ||
/// <param name="url">蓝奏云分享链接</param> | ||
/// <param name="key">加密密钥</param> | ||
/// <returns>返回解析后的直链,若失败则返回 null</returns> | ||
public static async Task<string?> GetDirectLinkAsync(string url, string key) | ||
{ | ||
return await GetUrlHelper.GetFullUrl(url, key); | ||
} | ||
} | ||
} |
Oops, something went wrong.