1
mirror of https://github.com/nilaoda/N_m3u8DL-CLI synced 2025-09-16 05:20:50 +02:00

Compare commits

..

17 Commits

Author SHA1 Message Date
dependabot[bot]
59cd026cf4 Bump Newtonsoft.Json from 13.0.1 to 13.0.2 in /N_m3u8DL-CLI
Bumps [Newtonsoft.Json](https://github.com/JamesNK/Newtonsoft.Json) from 13.0.1 to 13.0.2.
- [Release notes](https://github.com/JamesNK/Newtonsoft.Json/releases)
- [Commits](https://github.com/JamesNK/Newtonsoft.Json/compare/13.0.1...13.0.2)

---
updated-dependencies:
- dependency-name: Newtonsoft.Json
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-08 15:02:45 +00:00
nilaoda
0cc4a87a4c Update FUNDING.yml 2022-11-17 23:10:19 +08:00
nilaoda
66d0864d72 update discord link 2022-10-10 13:44:53 +08:00
nilaoda
965ac2b513 update discord link 2022-10-10 13:43:58 +08:00
nilaoda
a95334ec57 fix #718 2022-09-05 21:55:09 +08:00
nilaoda
e05a21a034 Merge pull request #714 from xifangczy/master
修复 录制间隔负数导致错误
2022-08-19 20:12:37 +08:00
O2bmm
13cd5d0870 修复 录制间隔负数导致错误 2022-08-19 19:38:03 +08:00
nilaoda
8d9ad7af41 Update README.md 2022-07-20 21:44:36 +08:00
nilaoda
0a11816acf fix #708 2022-07-20 21:34:18 +08:00
nilaoda
81ba4ff7d3 Create FUNDING.yml 2022-07-14 20:08:45 +08:00
nilaoda
f5a9ed08a1 update version 2022-07-12 00:21:39 +08:00
nilaoda
6b8bfde19f update docs 2022-07-12 00:10:53 +08:00
nilaoda
ff738f2849 Merge pull request #698 from xifangczy/master
fix: 修正m3u8dl协议 转义符问题
2022-07-11 23:44:31 +08:00
O2bmm
3d35c24a2e fix: 修正m3u8dl协议 转义符问题 2022-07-11 01:32:30 +08:00
nilaoda
41d7151e7e Update HLSLiveDownloader.cs 2022-06-22 11:43:36 +08:00
nilaoda
94246ef163 支持ChaCha20解密 2022-06-20 23:18:27 +08:00
nilaoda
9c118631cf 优化对#EXT-X-BYTERANGE的处理 2022-06-05 02:15:24 +08:00
22 changed files with 809 additions and 32 deletions

13
.github/FUNDING.yml vendored Normal file
View File

@@ -0,0 +1,13 @@
# These are supported funding model platforms
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
custom: ['https://nilaoda.github.io/N_m3u8DL-CLI/source/images/alipay.png','https://www.buymeacoffee.com/nilaoda']

661
N_m3u8DL-CLI/CSChaCha20.cs Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,7 @@
using System;
using CSChaCha20;
using System;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
namespace N_m3u8DL_CLI
@@ -45,6 +47,40 @@ namespace N_m3u8DL_CLI
return resultArray;
}
public static byte[] CHACHA20Decrypt(byte[] encryptedBuff, byte[] keyBytes, byte[] nonceBytes)
{
if (keyBytes.Length != 32)
throw new Exception("Key must be 32 bytes!");
if (nonceBytes.Length != 12 && nonceBytes.Length != 8)
throw new Exception("Key must be 12 or 8 bytes!");
if (nonceBytes.Length == 8)
nonceBytes = (new byte[4] { 0, 0, 0, 0 }).Concat(nonceBytes).ToArray();
var decStream = new MemoryStream();
using (BinaryReader reader = new BinaryReader(new MemoryStream(encryptedBuff)))
{
using (BinaryWriter writer = new BinaryWriter(decStream))
{
while (true)
{
var buffer = reader.ReadBytes(1024);
byte[] dec = new byte[buffer.Length];
if (buffer.Length > 0)
{
ChaCha20 forDecrypting = new ChaCha20(keyBytes, nonceBytes, 0);
forDecrypting.DecryptBytes(dec, buffer);
writer.Write(dec, 0, dec.Length);
}
else
{
break;
}
}
}
}
return decStream.ToArray();
}
public static byte[] HexStringToBytes(string hexStr)
{
if (string.IsNullOrEmpty(hexStr))

View File

@@ -47,6 +47,10 @@ namespace N_m3u8DL_CLI
public long ExpectByte { get => expectByte; set => expectByte = value; }
public long StartByte { get => startByte; set => startByte = value; }
public double SegDur { get => segDur; set => segDur = value; }
public static bool EnableChaCha20 { get; set; } = false;
public static string ChaCha20KeyBase64 { get; set; }
public static string ChaCha20NonceBase64 { get; set; }
//重写WebClinet
//private class WebClient : System.Net.WebClient
@@ -179,9 +183,18 @@ namespace N_m3u8DL_CLI
if (File.Exists(savePath) && Global.ShouldStop == false)
{
FileInfo fi = new FileInfo(savePath);
if (Method == "NONE" || method.Contains("NOTSUPPORTED"))
if (File.Exists(fi.FullName) && EnableChaCha20)
{
fi.MoveTo(Path.GetDirectoryName(savePath) + "\\" + Path.GetFileNameWithoutExtension(savePath) + ".ts");
byte[] decryptBuff = Decrypter.CHACHA20Decrypt(File.ReadAllBytes(fi.FullName), Convert.FromBase64String(ChaCha20KeyBase64), Convert.FromBase64String(ChaCha20NonceBase64));
FileStream fs = new FileStream(Path.GetDirectoryName(SavePath) + "\\" + Path.GetFileNameWithoutExtension(SavePath) + ".ts", FileMode.Create);
fs.Write(decryptBuff, 0, decryptBuff.Length);
fs.Close();
DownloadManager.DownloadedSize += fi.Length;
fi.Delete();
}
else if (Method == "NONE" || Method.Contains("NOTSUPPORTED"))
{
fi.MoveTo(Path.GetDirectoryName(SavePath) + "\\" + Path.GetFileNameWithoutExtension(SavePath) + ".ts");
DownloadManager.DownloadedSize += fi.Length;
//Console.WriteLine(Path.GetFileNameWithoutExtension(savePath) + " Completed.");
}
@@ -249,4 +262,4 @@ namespace N_m3u8DL_CLI
}
}
}
}
}

View File

@@ -35,7 +35,7 @@ namespace N_m3u8DL_CLI
/*===============================================================================*/
static Version ver = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;
static string nowVer = $"{ver.Major}.{ver.Minor}.{ver.Build}";
static string nowDate = "20220526";
static string nowDate = "20220711";
public static void WriteInit()
{
Console.WriteLine($"N_m3u8DL-CLI version {nowVer} 2018-2022");

View File

@@ -61,7 +61,7 @@ namespace N_m3u8DL_CLI
string m3u8Url = initJson["m3u8"].Value<string>();
targetduration = initJson["m3u8Info"]["targetDuration"].Value<double>();
TotalDuration = initJson["m3u8Info"]["totalDuration"].Value<double>();
timer.Interval = (TotalDuration - targetduration) * 1000;//设置定时器运行间隔
timer.Interval = Math.Abs(TotalDuration - targetduration) * 1000;//设置定时器运行间隔
if (timer.Interval <= 1000) timer.Interval = 10000;
JArray lastSegments = JArray.Parse(initJson["m3u8Info"]["segments"][0].ToString().Trim()); //上次的分段,用于比对新分段
ArrayList tempList = new ArrayList(); //所有待下载的列表
@@ -79,6 +79,7 @@ namespace N_m3u8DL_CLI
}
Parser parser = new Parser();
parser.Headers = Headers;
parser.DownDir = Path.GetDirectoryName(jsonFile);
parser.M3u8Url = m3u8Url;
parser.LiveStream = true;
@@ -128,6 +129,7 @@ namespace N_m3u8DL_CLI
sd.Iv = info["iv"].Value<string>();
}
sd.TimeOut = (int)timer.Interval - 1000;//超时时间不超过下次执行时间
if (sd.TimeOut <= 0) sd.TimeOut = (int)timer.Interval;
sd.SegIndex = index;
sd.Headers = Headers;
sd.SegDur = info["duration"].Value<double>();

View File

@@ -563,12 +563,19 @@ namespace N_m3u8DL_CLI
Console.Write("".PadRight(13) + "Enter Numbers Separated By A Space: ");
var input = Console.ReadLine();
cursorIndex += 2;
for (int i = startCursorIndex; i < cursorIndex; i++)
try
{
Console.SetCursorPosition(0, i);
Console.Write("".PadRight(300));
for (int i = startCursorIndex; i < cursorIndex; i++)
{
Console.SetCursorPosition(0, i);
Console.Write("".PadRight(300));
}
Console.SetCursorPosition(0, startCursorIndex);
}
catch (Exception)
{
;
}
Console.SetCursorPosition(0, startCursorIndex);
if (!string.IsNullOrEmpty(input))
{
bestVideo = new Dictionary<string, dynamic>() { ["Tbr"] = 0 };

View File

@@ -97,5 +97,14 @@ namespace N_m3u8DL_CLI
[Option("unregisterUrlProtocol", HelpText = "Help_unregisterUrlProtocol", ResourceType = typeof(strings))]
public bool UnregisterUrlProtocol { get; set; }
[Option("enableChaCha20", HelpText = "enableChaCha20")]
public bool EnableChaCha20 { get; set; }
[Option("chaCha20KeyBase64", HelpText = "ChaCha20KeyBase64")]
public string ChaCha20KeyBase64 { get; set; }
[Option("chaCha20NonceBase64", HelpText = "ChaCha20NonceBase64")]
public string ChaCha20NonceBase64 { get; set; }
}
}

View File

@@ -90,6 +90,7 @@
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="CSChaCha20.cs" />
<Compile Include="Decode51CtoKey.cs" />
<Compile Include="DecodeCdeledu.cs" />
<Compile Include="DecodeDdyun.cs" />

View File

@@ -271,6 +271,7 @@ namespace N_m3u8DL_CLI
{
expectByte = Convert.ToInt64(t[0]);
segInfo.Add("expectByte", expectByte);
segInfo.Add("startByte", segments.Last["startByte"].Value<long>() + segments.Last["expectByte"].Value<long>());
}
if (t.Length == 2)
{
@@ -635,12 +636,19 @@ namespace N_m3u8DL_CLI
Console.Write("".PadRight(13) + "Enter Number: ");
var input = Console.ReadLine();
cursorIndex += 2;
for (int i = startCursorIndex; i < cursorIndex; i++)
try
{
Console.SetCursorPosition(0, i);
Console.Write("".PadRight(300));
for (int i = startCursorIndex; i < cursorIndex; i++)
{
Console.SetCursorPosition(0, i);
Console.Write("".PadRight(300));
}
Console.SetCursorPosition(0, startCursorIndex);
}
catch (Exception)
{
;
}
Console.SetCursorPosition(0, startCursorIndex);
audioUrl = MEDIA_AUDIO_GROUP[bestUrlAudio][int.Parse(input)].Uri;
}
}
@@ -665,12 +673,19 @@ namespace N_m3u8DL_CLI
Console.Write("".PadRight(13) + "Enter Number: ");
var input = Console.ReadLine();
cursorIndex += 2;
for (int i = startCursorIndex; i < cursorIndex; i++)
try
{
Console.SetCursorPosition(0, i);
Console.Write("".PadRight(300));
for (int i = startCursorIndex; i < cursorIndex; i++)
{
Console.SetCursorPosition(0, i);
Console.Write("".PadRight(300));
}
Console.SetCursorPosition(0, startCursorIndex);
}
catch (Exception)
{
;
}
Console.SetCursorPosition(0, startCursorIndex);
subUrl = MEDIA_SUB_GROUP[bestUrlSub][int.Parse(input)].Uri;
}
}

View File

@@ -81,6 +81,8 @@ namespace N_m3u8DL_CLI.NetCore
var cmd = "";
try { cmd = Encoding.UTF8.GetString(Convert.FromBase64String(base64)); }
catch (FormatException) { cmd = Encoding.UTF8.GetString(Convert.FromBase64String(base64.TrimEnd('/'))); }
//修正参数转义符
cmd = cmd.Replace("\\\"", "\"");
//修正工作目录
Environment.CurrentDirectory = Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName);
args = Global.ParseArguments(cmd).ToArray(); //解析命令行
@@ -225,6 +227,13 @@ namespace N_m3u8DL_CLI.NetCore
workDir = Environment.ExpandEnvironmentVariables(o.WorkDir);
DownloadManager.HasSetDir = true;
}
//CHACHA20
if (o.EnableChaCha20 && !string.IsNullOrEmpty(o.ChaCha20KeyBase64) && !string.IsNullOrEmpty(o.ChaCha20NonceBase64))
{
Downloader.EnableChaCha20 = true;
Downloader.ChaCha20KeyBase64 = o.ChaCha20KeyBase64;
Downloader.ChaCha20NonceBase64 = o.ChaCha20NonceBase64;
}
//Proxy
if (!string.IsNullOrEmpty(o.ProxyAddress))

View File

@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号
// 方法是按如下所示使用“*”: :
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("3.0.1.0")]
[assembly: AssemblyFileVersion("3.0.1.0")]
[assembly: AssemblyVersion("3.0.2.0")]
[assembly: AssemblyFileVersion("3.0.2.0")]

View File

@@ -5,7 +5,7 @@
<package id="Costura.Fody" version="4.1.0" targetFramework="net46" />
<package id="Fody" version="6.0.0" targetFramework="net46" developmentDependency="true" />
<package id="HttpToSocks5Proxy" version="1.4.0" targetFramework="net46" />
<package id="Newtonsoft.Json" version="13.0.1" targetFramework="net46" />
<package id="Newtonsoft.Json" version="13.0.2" targetFramework="net46" />
<package id="NiL.JS" version="2.5.1428" targetFramework="net46" />
<package id="Resource.Embedder" version="2.1.1" targetFramework="net46" />
<package id="System.Runtime.CompilerServices.Unsafe" version="4.5.2" targetFramework="net46" />

View File

@@ -22,7 +22,9 @@
本项目已于2019年10月9日开源采用MIT许可证各取所需。
# 关于跨平台
未来可期
* N_m3u8DL-CLI `(本项目)`: 基于 .NET Framework, 不具备跨平台能力. 目前已进入维护阶段.
* [N_m3u8DL-RE](https://github.com/nilaoda/N_m3u8DL-RE) : 抛弃历史包袱从零做起, 支持Win/Linux/Mac, 更丰富的功能会在这里出现 ...
# N_m3u8DL-CLI
一个**简单易用的**m3u8下载器下载地址https://github.com/nilaoda/N_m3u8DL-CLI/releases
@@ -89,6 +91,9 @@ OPTIONS:
--noProxy 不自动使用系统代理
--registerUrlProtocol 注册m3u8dl链接协议
--unregisterUrlProtocol 取消注册m3u8dl链接协议
--enableChaCha20 enableChaCha20
--chaCha20KeyBase64 ChaCha20KeyBase64
--chaCha20NonceBase64 ChaCha20NonceBase64
--help Display this help screen.
--version Display version information.
```
@@ -119,7 +124,7 @@ URI解码结果
https://nilaoda.github.io/N_m3u8DL-CLI/
# 聊聊
https://discord.gg/W5tvcRJDPs
https://discord.gg/SSGwKrjC44
# 赞赏
![Wow](https://nilaoda.github.io/N_m3u8DL-CLI/source/images/alipay.png)

View File

@@ -68,6 +68,9 @@ OPTIONS:
--noProxy Disable use system proxy
--registerUrlProtocol Register m3u8dl URL protocol
--unregisterUrlProtocol Unregister m3u8dl URL protocol
--enableChaCha20 enableChaCha20
--chaCha20KeyBase64 ChaCha20KeyBase64
--chaCha20NonceBase64 ChaCha20NonceBase64
--help Display this help screen.
--version Display version information.
```
@@ -98,4 +101,4 @@ URI Decode Result
https://nilaoda.github.io/N_m3u8DL-CLI/
## Chit-chat
https://discord.gg/W5tvcRJDPs
https://discord.gg/RscAJZv3Yq

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long