Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions Core/Configs/Options.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ public Options(IEnumerable<string> url) {

[Option('p', "password", Required = false, HelpText = "Пароль от системы")]
public string Password { get; set; }

[Option('k', "token", Required = false, HelpText = "Готовый токен авторизации")]
public string Token { get; set; }

[Option("proxy", Required = false, HelpText = "Прокси в формате <host>:<port>")]
public string Proxy { get; set; }
Expand Down Expand Up @@ -74,6 +77,12 @@ public Options(IEnumerable<string> url) {

[Option("book-name-pattern", Required = false, HelpText = "Шаблон имени файла.", Default = "{Author.Name} - {Book.Title}")]
public string BookNamePattern { get; set; } = "{Author.Name} - {Book.Title}";

[Option("split-volumes", Required = false, HelpText = "Разбивать по томам (если поддерживается)")]
public bool SplitVolumes { get; set; }

[Option("split-chapters", Required = false, HelpText = "Разбивать по главам (если поддерживается)")]
public bool SplitChapters { get; set; }

public bool HasAdditionalType(AdditionalTypeEnum type) => Additional && (AdditionalTypes == default || !AdditionalTypes.Any() || AdditionalTypes.Contains(type));

Expand Down
12 changes: 11 additions & 1 deletion Core/Logic/Builders/BuilderBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ public abstract class BuilderBase(Options options, ILogger logger) {
/// <param name="book">Книга</param>
/// <param name="fileName">Имя файла</param>
protected abstract Task BuildInternal(Book book, string fileName);
protected virtual async Task SplitBuild(Book book, string fileName) { await BuildInternal(book, fileName); }

/// <summary>
/// Получение имени файла
Expand All @@ -41,6 +42,11 @@ public abstract class BuilderBase(Options options, ILogger logger) {
/// <param name="book">Книга</param>
public async Task Build(Book book) {
var fileName = GetFileName(book);

if (book.SupportSplitting && (Options.SplitChapters || Options.SplitVolumes))
{
fileName = GetTitle(book);
}

if (!string.IsNullOrWhiteSpace(Options.SavePath)) {
if (!Directory.Exists(Options.SavePath)) {
Expand All @@ -51,7 +57,11 @@ public async Task Build(Book book) {
}

Logger.LogInformation($"Начинаю сохранение книги {fileName.CoverQuotes()}");
await BuildInternal(book, fileName);
if (book.SupportSplitting && (Options.SplitChapters || Options.SplitVolumes)) {
await SplitBuild(book, fileName);
} else {
await BuildInternal(book, fileName);
}

if (Options.Cover) {
await SaveCover(Options.SavePath, book.Cover, GetTitle(book));
Expand Down
126 changes: 116 additions & 10 deletions Core/Logic/Builders/CbzBuilder.cs
Original file line number Diff line number Diff line change
@@ -1,34 +1,140 @@
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Threading.Tasks;
using Core.Configs;
using Core.Types.Book;
using Microsoft.Extensions.Logging;

namespace Core.Logic.Builders;
namespace Core.Logic.Builders;

public class CbzBuilder(Options options, ILogger logger) : BuilderBase(options, logger) {
public class CbzBuilder(Options options, ILogger logger) : BuilderBase(options, logger)
{
protected override string Extension => "cbz";

protected override async Task BuildInternal(Book book, string fileName) {
if (File.Exists(fileName)) {
protected override async Task BuildInternal(Book book, string fileName)
{
if (File.Exists(fileName))
{
File.Delete(fileName);
}

using var archive = ZipFile.Open(fileName, ZipArchiveMode.Create);

var c = 0;
foreach (var chapter in book.Chapters) {
if (chapter.Images == default) {
foreach (var chapter in book.Chapters)
{
if (chapter.Images == default)
{
continue;
}

foreach (var image in chapter.Images) {
var entry = archive.CreateEntry($"{++c}{image.Extension}", CompressionLevel.Optimal);
foreach (var image in chapter.Images)
{
var image_name = $"{chapter.VolumeNumber}-{chapter.ChapterNumber}-{++c}{image.Extension}";
var entry = archive.CreateEntry(image_name, CompressionLevel.Optimal);
await using var entryStream = entry.Open();
await using var fileStream = image.GetStream();
await fileStream.CopyToAsync(entryStream);
}
}
}

protected override async Task SplitBuild(Book book, string fileName)
{
if (options.SplitVolumes && options.SplitChapters)
{
foreach (var volumeNumber in book.Volumes)
{
var volume_name = $"{fileName}.v{volumeNumber}.{Extension}";
using var volume_archive = ZipFile.Open(volume_name, ZipArchiveMode.Create);

foreach (var chapter in book.Chapters.Where(c => c.VolumeNumber == volumeNumber))
{
if (chapter.Images == default)
{
continue;
}

var chapter_name = $"{fileName}.v{chapter.VolumeNumber}.c{chapter.ChapterNumber}.{Extension}";

using var chapter_archive = ZipFile.Open(chapter_name, ZipArchiveMode.Create);

var c = 0;
foreach (var image in chapter.Images)
{
var image_name = $"{chapter.VolumeNumber}-{chapter.ChapterNumber}-{++c}{image.Extension}";
var volume_entry = volume_archive.CreateEntry(image_name, CompressionLevel.Optimal);
var chapter_entry = chapter_archive.CreateEntry(image_name, CompressionLevel.Optimal);
await using var volume_entryStream = volume_entry.Open();
await using var chapter_entryStream = chapter_entry.Open();
await using var volume_fileStream = image.GetStream();
await using var chapter_fileStream = image.GetStream();
await volume_fileStream.CopyToAsync(volume_entryStream);
await chapter_fileStream.CopyToAsync(chapter_entryStream);
}
Logger.LogInformation($"Книга {chapter_name} успешно сохранена");
chapter_archive.Dispose();
}
Logger.LogInformation($"Книга {volume_name} успешно сохранена");
volume_archive.Dispose();
}
}
else if (options.SplitVolumes)
{
foreach (var volumeNumber in book.Volumes)
{
var volume_name = $"{fileName}.v{volumeNumber}.{Extension}";

using var volume_archive = ZipFile.Open(volume_name, ZipArchiveMode.Create);

var c = 0;
foreach (var chapter in book.Chapters.Where(c => c.VolumeNumber == volumeNumber))
{
if (chapter.Images == default)
{
continue;
}
foreach (var image in chapter.Images)
{
var image_name = $"{chapter.VolumeNumber}-{chapter.ChapterNumber}-{++c}{image.Extension}";
var volume_entry = volume_archive.CreateEntry(image_name, CompressionLevel.Optimal);
await using var volume_entryStream = volume_entry.Open();
await using var fileStream = image.GetStream();
await fileStream.CopyToAsync(volume_entryStream);
}
}
Logger.LogInformation($"Книга {volume_name} успешно сохранена");
volume_archive.Dispose();
}
}
else if (options.SplitChapters)
{
foreach (var chapter in book.Chapters)
{
var chapter_name = $"{fileName}.v{chapter.VolumeNumber}.c{chapter.ChapterNumber}.{Extension}";

using var chapter_archive = ZipFile.Open(chapter_name, ZipArchiveMode.Create);
if (chapter.Images == default)
{
continue;
}
var c = 0;
foreach (var image in chapter.Images)
{
var image_name = $"{chapter.VolumeNumber}-{chapter.ChapterNumber}-{++c}{image.Extension}";
var chapter_entry = chapter_archive.CreateEntry(image_name, CompressionLevel.Optimal);
await using var chapter_entryStream = chapter_entry.Open();
await using var fileStream = image.GetStream();
await fileStream.CopyToAsync(chapter_entryStream);
}
Logger.LogInformation($"Книга {chapter_name} успешно сохранена");
chapter_archive.Dispose();
}
}
else
{
await BuildInternal(book, fileName);
}
}
}
Loading