Skip to content

Commit a369fc8

Browse files
committed
* Adding the ability to clear cache
* Fixing defect with upload utils not working with parallel files * Adding download util * Edits to rate limits * Adding events * Adding pagination downloader * Adding default verb for utils
1 parent 0571f06 commit a369fc8

34 files changed

+2783
-112
lines changed

src/MangaDexSharp.Cli/Verbs/UploadVerb.cs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,16 @@ public override async Task<bool> Execute(UploadVerbOptions options, Cancellation
3838

3939
_logger.LogInformation("Session ID: {id}", session.SessionId);
4040

41-
foreach (var file in files)
42-
{
43-
await session.UploadFile(file);
44-
}
41+
await Task.WhenAll(files.Select(t => session.UploadFile(t)));
42+
43+
//foreach (var file in files)
44+
//{
45+
// await session.UploadFile(file);
46+
//}
4547

4648
var chapter = await session.Commit(new ChapterDraft
4749
{
48-
Chapter = "1337",
50+
Chapter = "1338",
4951
Title = "Automated Test Chapter - MDSharp",
5052
TranslatedLanguage = "en",
5153
Volume = "69"

src/MangaDexSharp.Utilities.Cli/AuthOptions.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,22 @@
33
public class AuthOptions
44
{
55
[Option('a', "access-token", HelpText = "Your account access token, if you have one. (You can get this from your browser's dev tools.)")]
6+
[Secret]
67
public string? AccessToken { get; set; }
78

89
[Option('c', "client-id", HelpText = "The client ID to use for the request. (You can get this from: https://mangadex.org/settings > API Clients)")]
10+
[Secret]
911
public string? ClientId { get; set; }
1012

1113
[Option('s', "client-secret", HelpText = "The client secret to use for the request. (You can get this from: https://mangadex.org/settings > API Clients)")]
14+
[Secret]
1215
public string? ClientSecret { get; set; }
1316

1417
[Option('u', "username", HelpText = "The username of your MangaDex account.")]
18+
[Secret]
1519
public string? Username { get; set; }
1620

1721
[Option('p', "password", HelpText = "The password of your MangaDex account.")]
22+
[Secret]
1823
public string? Password { get; set; }
1924
}

src/MangaDexSharp.Utilities.Cli/Extensions.cs

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,22 @@
1-
namespace MangaDexSharp.Utilities.Cli;
1+
using Spectre.Console;
2+
3+
namespace MangaDexSharp.Utilities.Cli;
24

35
public static class Extensions
46
{
7+
public static string Trim(this string text, int maxLength, string replacer = "...")
8+
{
9+
if (text.Length > maxLength)
10+
return text[..(maxLength - replacer.Length)] + replacer;
11+
return text;
12+
}
13+
14+
public static string Escape(this string text, int buffer = 5)
15+
{
16+
var maxLength = Console.WindowWidth - buffer;
17+
return Markup.Escape(text.Trim(maxLength));
18+
}
19+
520
public static IEnumerable<T[]> Batch<T>(this IEnumerable<T> input, int size)
621
{
722
var batch = new List<T>(size);
@@ -18,4 +33,21 @@ public static IEnumerable<T[]> Batch<T>(this IEnumerable<T> input, int size)
1833

1934
yield return batch.ToArray();
2035
}
36+
37+
public static T ConsoleSelect<T>(this IEnumerable<T> items, string? prompt = null, Func<T, string>? display = null)
38+
where T : notnull
39+
{
40+
if (items is null || !items.Any()) throw new NullReferenceException("Items cannot be null or empty.");
41+
42+
prompt = Escape(prompt ?? $"Please select a {typeof(T).Name}:");
43+
display ??= item => item?.ToString() ?? string.Empty;
44+
45+
var select = new SelectionPrompt<T>()
46+
.Title(prompt)
47+
.PageSize(Console.WindowHeight - 5)
48+
.MoreChoicesText("[grey](Move up and down to reveal more choices)[/]")
49+
.UseConverter(t => display(t))
50+
.AddChoices(items);
51+
return AnsiConsole.Prompt(select);
52+
}
2153
}

src/MangaDexSharp.Utilities.Cli/MangaDexSharp.Utilities.Cli.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
<PackageReference Include="CsvHelper" Version="33.0.1" />
1414
<PackageReference Include="Serilog.Extensions.Logging" Version="8.0.0" />
1515
<PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" />
16+
<PackageReference Include="Spectre.Console" Version="0.50.0" />
1617
</ItemGroup>
1718

1819
<ItemGroup>

src/MangaDexSharp.Utilities.Cli/Program.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,8 @@
1212
.AddTransient<IExportReadListService, ExportReadListService>()
1313
.Cli(args, c =>
1414
{
15-
c.Add<ExportReadListVerb>();
15+
c.Add<ExportReadListVerb>()
16+
.Add<CheckAuthVerb>()
17+
.Add<DefaultVerb>()
18+
.Add<DownloadVerb>();
1619
});
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
namespace MangaDexSharp.Utilities.Cli;
2+
3+
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
4+
public class SecretAttribute : Attribute { }

src/MangaDexSharp.Utilities.Cli/Services/ExportReadListService.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
namespace MangaDexSharp.Utilities.Cli.Services;
22

3+
using CardboardBox.Extensions;
34
using System.Text;
45
using Writers;
56
using MangaStatus = (Manga manga, ReadStatus status, Chapter? chapter);
@@ -137,7 +138,7 @@ public static CsvManga FromManga(MangaStatus m, string lang)
137138

138139
return new CsvManga(
139140
m.manga.Id,
140-
m.manga.Attributes?.Title?.PreferedOrFirst(t => t.Key == lang).Value ?? string.Empty,
141+
m.manga.Attributes?.Title?.PreferredOrFirst(t => t.Key == lang).Value ?? string.Empty,
141142
coverUrl,
142143
$"https://mangadex.org/title/{m.manga.Id}",
143144
m.status.ToString(),
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
namespace MangaDexSharp.Utilities.Cli.Verbs;
2+
3+
using Services;
4+
5+
[Verb("check-auth", HelpText = "Check to see if the given authentication is valid.")]
6+
public class CheckAuthOptions : AuthOptions
7+
{
8+
9+
}
10+
11+
internal class CheckAuthVerb(
12+
ILogger<CheckAuthVerb> logger,
13+
AuthOptionsCache _cache,
14+
IMangaDex _md,
15+
IMdJsonService _json) : BooleanVerb<CheckAuthOptions>(logger)
16+
{
17+
public override async Task<bool> Execute(CheckAuthOptions options, CancellationToken token)
18+
{
19+
_cache.Auth = options;
20+
var me = await _md.User.Me();
21+
if (me.IsError(out var errors))
22+
{
23+
_logger.LogError("Authentication failed: {Errors}", string.Join(", ", errors));
24+
return false;
25+
}
26+
27+
_logger.LogInformation("Authentication successful! Profile: {profile}", _json.Pretty(me));
28+
return true;
29+
}
30+
}

0 commit comments

Comments
 (0)