Skip to content

Commit

Permalink
feat: replace CommandLineParser with System.CommandLine
Browse files Browse the repository at this point in the history
  • Loading branch information
tautcony committed Dec 5, 2023
1 parent 01a9d1c commit efb2939
Show file tree
Hide file tree
Showing 2 changed files with 202 additions and 127 deletions.
12 changes: 7 additions & 5 deletions OKP.Core/OKP.Core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,22 @@
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<PublishSingleFile>true</PublishSingleFile>
<PublishSingleFile>true</PublishSingleFile>
<Version>1.0.2-beta</Version>
<Copyright>Copyright (C) 2023 AmusementClub
Released under the GNU GPLv3+.
</Copyright>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="BencodeNET" Version="4.0.0" />
<PackageReference Include="CommandLineParser" Version="2.9.1" />
<PackageReference Include="BencodeNET" Version="5.0.0" />
<PackageReference Include="Polly.Extensions.Http" Version="3.0.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" />
<PackageReference Include="Serilog" Version="3.1.1" />
<PackageReference Include="Serilog.Sinks.Console" Version="5.0.1" />
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
<PackageReference Include="Tomlyn" Version="0.16.2" />
<PackageReference Include="Spectre.Console" Version="0.48.0" />
<PackageReference Include="System.CommandLine" Version="2.0.0-beta4.22272.1" />
<PackageReference Include="Tomlyn" Version="0.17.0" />
</ItemGroup>

<ItemGroup>
Expand Down
317 changes: 195 additions & 122 deletions OKP.Core/Program.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
using CommandLine;
using System.CommandLine;
using System.CommandLine.Builder;
using System.CommandLine.Help;
using System.CommandLine.Parsing;
using OKP.Core.Interface;
using OKP.Core.Interface.Acgnx;
using OKP.Core.Interface.Acgrip;
Expand All @@ -9,136 +12,206 @@
using Serilog;
using Serilog.Core;
using Serilog.Events;
using Spectre.Console;
using Constants = OKP.Core.Utils.Constants;

namespace OKP.Core
{
// ReSharper disable once ClassNeverInstantiated.Global
internal class Program
{
#pragma warning disable CS8618

private class Options
{
[Value(0, Min = 1, Required = true, MetaName = "torrent", HelpText = "Torrents to be published.(Or Cookie file exported by Get Cookies.txt.)")]
public IEnumerable<string>? TorrentFile { get; set; }
[Option("cookies", Required = false, Default = null, HelpText = "Cookie file to be used.")]
public string? Cookies { get; set; }
[Option('s', "setting", Required = false, Default = Constants.DefaultSettingFileName, HelpText = "(Not required) Specific setting file.")]
public string SettingFile { get; set; }
[Option('l', "log_level", Default = "Debug", HelpText = "Log level.")]
public string? LogLevel { get; set; }
[Option("log_file", Required = false, Default = Constants.DefaultLogFileName, HelpText = "Log file.")]
public string LogFile { get; set; }
[Option('y', HelpText = "Skip reaction.")]
public bool NoReaction { get; set; }
[Option("allow_skip",HelpText="Ignore login fail and continue publishing.")]
public bool AllowSkip { get;set; }
}
#pragma warning restore CS8618

public static void Main(string[] args)
{
Parser.Default.ParseArguments<Options>(args)
.WithParsed(o =>
{
var levelSwitch = new LoggingLevelSwitch
{
MinimumLevel = o.LogLevel?.ToLower() switch
{
"verbose" => LogEventLevel.Verbose,
"debug" => LogEventLevel.Debug,
"info" => LogEventLevel.Information,
_ => LogEventLevel.Debug
}
};
Log.Logger = new LoggerConfiguration()
.MinimumLevel.ControlledBy(levelSwitch)
.WriteTo.Console()
.WriteTo.File(o.LogFile,
rollingInterval: RollingInterval.Month,
rollOnFileSizeLimit: true)
.CreateLogger();
IOHelper.NoReaction = o.NoReaction;
if (o.TorrentFile is null)
{
Log.Fatal("o.TorrentFile is null");
return;
}
var addCookieCount = 0;
foreach (var file in o.TorrentFile)
{
if (!File.Exists(file))
{
Log.Error("文件{File}不存在", file);
continue;
}
var extension = (Path.GetExtension(file) ?? "").ToLower();
var torrentArgument = new Argument<IEnumerable<string>?>(
name: "torrent",
description: "Torrents to be published. (Or Cookie file exported by Get Cookies.txt.)"
);

var cookiesOption = new Option<string?>(
name: "--cookies",
getDefaultValue: () => null,
description: "Cookie file to be used."
);

var settingOption = new Option<string>(
name: "--setting",
getDefaultValue: () => Constants.DefaultSettingFileName,
description: "(Not required) Specific setting file."
);
settingOption.AddAlias("-s");

var logLevelOption = new Option<string?>(
name: "--log_level",
getDefaultValue: () => "Debug",
description: "Log level."
);
logLevelOption.AddAlias("-l");

var logFileOption = new Option<string>(
name: "--log_file",
getDefaultValue: () => Constants.DefaultLogFileName,
description: "Log file."
);

var noReactionOption = new Option<bool>(
name: "--no_reaction",
description: "Skip reaction."
);
noReactionOption.AddAlias("-y");

var allowSkipOption = new Option<bool>(
name: "--allow_skip",
description: "Ignore login fail and continue publishing."
);

var rootCommand = new RootCommand("One Key Publish")
{
torrentArgument,
cookiesOption,
settingOption,
logLevelOption,
logFileOption,
noReactionOption,
allowSkipOption,
};

rootCommand.SetHandler((
torrentFile,
cookies,
settingFile,
logLevel,
logFile,
noReaction,
allowSkip) =>
{
var levelSwitch = new LoggingLevelSwitch
{
MinimumLevel = logLevel?.ToLower() switch
{
"verbose" => LogEventLevel.Verbose,
"debug" => LogEventLevel.Debug,
"info" => LogEventLevel.Information,
_ => LogEventLevel.Debug
}
};
Log.Logger = new LoggerConfiguration()
.MinimumLevel.ControlledBy(levelSwitch)
.WriteTo.Console()
.WriteTo.File(logFile,
rollingInterval: RollingInterval.Month,
rollOnFileSizeLimit: true)
.CreateLogger();
IOHelper.NoReaction = noReaction;
if (torrentFile is null)
{
Log.Fatal("o.TorrentFile is null");
return;
}
var addCookieCount = 0;
foreach (var file in torrentFile)
{
if (!File.Exists(file))
{
Log.Error("文件{File}不存在", file);
continue;
}
var extension = (Path.GetExtension(file) ?? "").ToLower();

if (extension == ".torrent")
{
Log.Information("正在发布 {File}", file);
SinglePublish(file, settingFile, cookies, allowSkip);
continue;
}
if (extension == ".txt")
{
if (cookies is null)
{
Log.Information("请输入Cookie文件名,不需要包含扩展名,相对目录默认为{DefaultPath}",
IOHelper.BasePath(Constants.DefaultCookiePath));
IOHelper.HintText(Constants.DefaultCookieFile);
var filename = IOHelper.ReadLine();
if (File.Exists(filename))
{
cookies = filename;
Log.Error("你指定的Cookie文件{File}已经存在!继续添加可能会覆盖之前保存的Cookie!", cookies);
IOHelper.ReadLine();
HttpHelper.GlobalCookieContainer.LoadFromTxt(cookies);
}
else
{
if (!Directory.Exists(IOHelper.BasePath(Constants.DefaultCookiePath)))
{
Directory.CreateDirectory(IOHelper.BasePath(Constants.DefaultCookiePath));
}
cookies = IOHelper.BasePath(Constants.DefaultCookiePath,
(filename?.Length == 0 ? Constants.DefaultCookieFile : filename) + ".txt");
if (File.Exists(cookies))
{
Log.Error("你指定的Cookie文件{File}已经存在!继续添加可能会覆盖之前保存的Cookie!", cookies);
IOHelper.ReadLine();
HttpHelper.GlobalCookieContainer.LoadFromTxt(cookies);
}
}
Log.Information("请输入你使用的浏览器UserAgent:");
var ua = IOHelper.ReadLine();
while (ua is null || !HttpHelper.UaRegex.IsMatch(ua))
{
Log.Information("你必须输入一个合法的UserAgent以确保你的cookie可以正常使用:");
ua = IOHelper.ReadLine();
}
HttpHelper.GlobalUserAgent = ua;
}
if (File.Exists(IOHelper.BasePath(Constants.DefaultCookiePath,
Constants.DefaultCookieFile + ".txt")))
{
HttpHelper.GlobalCookieContainer.LoadFromTxt(IOHelper.BasePath(Constants.DefaultCookiePath,
Constants.DefaultCookieFile + ".txt"));
}
Log.Information("正在添加Cookie文件{File}", file);
AddCookies(file);
addCookieCount++;
Log.Information("Cookie文件{File}添加完成,按回车键继续添加", file);
IOHelper.ReadLine();
}
else
{
Log.Error("不受支持的文件格式{File}", file);
}
if (cookies is not null)
{
Log.Information("共输入了{Count}个Cookie文件", addCookieCount);
HttpHelper.GlobalCookieContainer.SaveToTxt(cookies, HttpHelper.GlobalUserAgent);
Log.Information("保存成功,Cookie文件保存在{Path}", cookies);
}
}
},
torrentArgument,
cookiesOption,
settingOption,
logLevelOption,
logFileOption,
noReactionOption,
allowSkipOption);

var parser = new CommandLineBuilder(rootCommand)
.UseDefaults()
.UseHelp(ctx =>
{
ctx.HelpBuilder.CustomizeLayout(
_ =>
HelpBuilder.Default
.GetLayout()
.Skip(1) // Skip the default command description section.
.Prepend(hc => hc.Output.Write("Copyright (C) 2023 AmusementClub\nReleased under the GNU GPLv3+.\n"))
.Prepend(
_ => AnsiConsole.Write(
new FigletText(rootCommand.Description!))
));
})
.Build();

if (extension == ".torrent")
{
Log.Information("正在发布 {File}", file);
SinglePublish(file, o.SettingFile, o.Cookies,o.AllowSkip);
continue;
}
if (extension == ".txt")
{
if (o.Cookies is null)
{
Log.Information("请输入Cookie文件名,不需要包含扩展名,相对目录默认为{DefaultPath}", IOHelper.BasePath(Constants.DefaultCookiePath));
IOHelper.HintText(Constants.DefaultCookieFile);
var filename = IOHelper.ReadLine();
if (File.Exists(filename))
{
o.Cookies = filename;
Log.Error("你指定的Cookie文件{File}已经存在!继续添加可能会覆盖之前保存的Cookie!", o.Cookies);
IOHelper.ReadLine();
HttpHelper.GlobalCookieContainer.LoadFromTxt(o.Cookies);
}
else
{
if (!Directory.Exists(IOHelper.BasePath(Constants.DefaultCookiePath)))
{
Directory.CreateDirectory(IOHelper.BasePath(Constants.DefaultCookiePath));
}
o.Cookies = IOHelper.BasePath(Constants.DefaultCookiePath, (filename?.Length == 0 ? Constants.DefaultCookieFile : filename) + ".txt");
if (File.Exists(o.Cookies))
{
Log.Error("你指定的Cookie文件{File}已经存在!继续添加可能会覆盖之前保存的Cookie!", o.Cookies);
IOHelper.ReadLine();
HttpHelper.GlobalCookieContainer.LoadFromTxt(o.Cookies);
}
}
Log.Information("请输入你使用的浏览器UserAgent:");
var ua = IOHelper.ReadLine();
while (ua is null || !HttpHelper.UaRegex.IsMatch(ua))
{
Log.Information("你必须输入一个合法的UserAgent以确保你的cookie可以正常使用:");
ua = IOHelper.ReadLine();
}
HttpHelper.GlobalUserAgent = ua;
}
if (File.Exists(IOHelper.BasePath(Constants.DefaultCookiePath, Constants.DefaultCookieFile + ".txt")))
{
HttpHelper.GlobalCookieContainer.LoadFromTxt(IOHelper.BasePath(Constants.DefaultCookiePath, Constants.DefaultCookieFile + ".txt"));
}
Log.Information("正在添加Cookie文件{File}", file);
AddCookies(file);
addCookieCount++;
Log.Information("Cookie文件{File}添加完成,按回车键继续添加", file);
IOHelper.ReadLine();
}
else
{
Log.Error("不受支持的文件格式{File}", file);
}
if (o.Cookies is not null)
{
Log.Information("共输入了{Count}个Cookie文件", addCookieCount);
HttpHelper.GlobalCookieContainer.SaveToTxt(o.Cookies, HttpHelper.GlobalUserAgent);
Log.Information("保存成功,Cookie文件保存在{Path}", o.Cookies);
}
}
});
parser.Invoke(args);
IOHelper.ReadLine();
}
private static void SinglePublish(string file, string settingFile, string? cookies,bool allowSkip)
Expand Down

0 comments on commit efb2939

Please sign in to comment.