Refactoring and new methods

main
Ogoun 5 months ago
parent 431f2503a8
commit 112daccec9

@ -0,0 +1,97 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\BukiVedi.Shared\BukiVedi.Shared.csproj" />
</ItemGroup>
<ItemGroup>
<None Update="config.ini">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="web\assets\cover.jpg">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="web\assets\search.svg">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="web\css\buki-common.css">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="web\css\common.css">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="web\css\fonts\Roboto-300.ttf">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="web\css\fonts\Roboto-300.woff">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="web\css\fonts\Roboto-300.woff2">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="web\css\fonts\Roboto-400.ttf">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="web\css\fonts\Roboto-400.woff">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="web\css\fonts\Roboto-400.woff2">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="web\css\login.css">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="web\css\logo.css">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="web\css\main.css">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="web\css\normalize.css">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="web\images\favicon.ico">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="web\images\flower.jpeg">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="web\index.html">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="web\js\bukivedi-auth.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="web\js\bukivedi.js">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="web\js\common\jquery.js">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="web\js\constants\index.js">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="web\js\jquery.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="web\js\login\index.js">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="web\js\main\index.js">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="web\js\requests\index.js">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="web\login.html">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>

@ -6,6 +6,40 @@
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<None Remove="web\css\fonts\Raleway-Italic-VariableFont_wght.ttf" />
<None Remove="web\css\fonts\Raleway-VariableFont_wght.ttf" />
<None Remove="web\css\fonts\Roboto-300.ttf" />
<None Remove="web\css\fonts\Roboto-300.woff" />
<None Remove="web\css\fonts\Roboto-300.woff2" />
<None Remove="web\css\fonts\Roboto-400.ttf" />
<None Remove="web\css\fonts\Roboto-400.woff" />
<None Remove="web\css\fonts\Roboto-400.woff2" />
</ItemGroup>
<ItemGroup>
<Page Include="web\css\fonts\Raleway-Italic-VariableFont_wght.ttf" />
<Page Include="web\css\fonts\Raleway-VariableFont_wght.ttf" />
<Page Include="web\css\fonts\Roboto-300.ttf">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Page>
<Page Include="web\css\fonts\Roboto-300.woff">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Page>
<Page Include="web\css\fonts\Roboto-300.woff2">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Page>
<Page Include="web\css\fonts\Roboto-400.ttf">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Page>
<Page Include="web\css\fonts\Roboto-400.woff">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Page>
<Page Include="web\css\fonts\Roboto-400.woff2">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Page>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\BukiVedi.Shared\BukiVedi.Shared.csproj" />
</ItemGroup>
@ -15,52 +49,79 @@
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="web\assets\cover.jpg">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="web\assets\heart.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="web\assets\heart_full.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="web\assets\search.svg">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="web\css\buki-common.css">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="web\css\common.css">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="web\css\fonts\Roboto-300.ttf">
<None Update="web\css\login.css">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="web\css\fonts\Roboto-300.woff">
<None Update="web\css\logo.css">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="web\css\fonts\Roboto-300.woff2">
<None Update="web\css\main.css">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="web\css\fonts\Roboto-400.ttf">
<None Update="web\css\normalize.css">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="web\css\fonts\Roboto-400.woff">
<None Update="web\css\scroll.css">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="web\css\fonts\Roboto-400.woff2">
<None Update="web\fonts\Roboto-Black.ttf">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="web\css\login.css">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<None Update="web\fonts\Roboto-BlackItalic.ttf">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="web\css\logo.css">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<None Update="web\fonts\Roboto-Bold.ttf">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="web\css\main.css">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<None Update="web\fonts\Roboto-BoldItalic.ttf">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="web\css\normalize.css">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<None Update="web\fonts\Roboto-Italic.ttf">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="web\fonts\Roboto-Light.ttf">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="web\fonts\Roboto-LightItalic.ttf">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="web\fonts\Roboto-Medium.ttf">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="web\fonts\Roboto-MediumItalic.ttf">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="web\fonts\Roboto-Regular.ttf">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="web\fonts\Roboto-Thin.ttf">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="web\fonts\Roboto-ThinItalic.ttf">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="web\images\favicon.ico">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="web\images\flower.jpeg">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="web\index.html">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
@ -72,26 +133,32 @@
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="web\js\common\jquery.js">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="web\js\constants\index.js">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="web\js\jquery.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="web\js\login\index.js">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="web\js\main\index.js">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="web\js\requests\index.js">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="web\js\scroll\index.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="web\login.html">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="web\script.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>

@ -1,10 +1,7 @@
using BukiVedi.App.Responces;
using BukiVedi.App.Services.Mappers;
using BukiVedi.Shared.Entities;
using BukiVedi.Shared.Services;
using BukiVedi.Shared.Apps;
using BukiVedi.Shared.Models;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using MongoDB.Driver;
namespace BukiVedi.App.Controllers
{
@ -14,11 +11,31 @@ namespace BukiVedi.App.Controllers
public class AuthorsController
: BaseController
{
private readonly ILibrary _library;
public AuthorsController(ILibrary library)
private readonly IAuthorHandler _handler;
public AuthorsController(IAuthorHandler handler)
: base()
{
_library = library;
_handler = handler;
}
/// <summary>
/// Получить список всех авторов
/// </summary>
/// <returns>Список авторов</returns>
[HttpGet()]
public async Task<ActionResult<IEnumerable<AuthorInfo>>> GetAllAuthors()
{
return Ok(await _handler.GetAllAuthors(OperationContext));
}
/// <summary>
/// Получить список авторов, которых пользователь добавил в избранное
/// </summary>
/// <returns>Список авторов</returns>
[HttpGet("favorite")]
public async Task<ActionResult<IEnumerable<AuthorInfo>>> GetFavoriteAuthors()
{
return Ok(await _handler.GetFavoriteAuthors(OperationContext));
}
/// <summary>
@ -27,33 +44,31 @@ namespace BukiVedi.App.Controllers
/// <param name="id">Идентификатор автора</param>
/// <returns>Список книг</returns>
[HttpPost("{id}/books")]
public async Task<ActionResult<IEnumerable<BookResponse>>> SearchByAuthor([FromRoute] string id)
public async Task<ActionResult<IEnumerable<BookInfo>>> SearchByAuthor([FromRoute] string id)
{
var books = (await _library.SearchBooksByAuthor(id)).ToArray();
return Ok(await BookEntityMapper.Map(books));
return Ok(await _handler.SearchByAuthor(id, OperationContext));
}
/// <summary>
/// Получить список всех авторов
/// Добавление автора в избранные
/// </summary>
/// <returns>Список авторов</returns>
[HttpGet()]
public async Task<ActionResult<IEnumerable<AuthorInfo>>> GetAllAuthors()
/// <returns>Ok</returns>
[HttpPost("favorite/{id}")]
public async Task<IActionResult> AppendToFavorites([FromRoute] string id)
{
var authors = (await Tables.Authors.GetAll()).Select(a => new AuthorInfo { Id = a.Id, Name = a.Name }).ToArray();
return Ok(authors);
await _handler.AddToFavorite(id, OperationContext);
return Ok();
}
/// <summary>
/// Получить список авторов, которых пользователь добавил в избранное
/// Удаление автора из избранных
/// </summary>
/// <returns>Список авторов</returns>
[HttpGet("favorite")]
public async Task<ActionResult<IEnumerable<AuthorInfo>>> GetFavoriteAuthors()
/// <returns>Ok</returns>
[HttpDelete("favorite/{id}")]
public async Task<IActionResult> RemoveFromFavorites([FromRoute] string id)
{
var authorIds = (await Tables.FavoriteAuthors.Get(Builders<FavoriteAuthor>.Filter.Eq(f => f.UserId, OperationContext.OperationInitiator.Id))).Select(f => f.AuthorId).ToHashSet();
var authors = (await Tables.Authors.Get(Builders<Author>.Filter.In(a => a.Id, authorIds))).Select(a => new AuthorInfo { Id = a.Id, Name = a.Name }).ToArray();
return Ok(authors);
await _handler.RemoveFromFavorite(id, OperationContext);
return Ok();
}
}
}

@ -1,11 +1,8 @@
using BukiVedi.App.Requests;
using BukiVedi.App.Responces;
using BukiVedi.App.Services.Mappers;
using BukiVedi.Shared.Entities;
using BukiVedi.Shared.Services;
using BukiVedi.Shared.Apps;
using BukiVedi.Shared.Models;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using MongoDB.Driver;
namespace BukiVedi.App.Controllers
{
@ -15,11 +12,11 @@ namespace BukiVedi.App.Controllers
public class BooksController
: BaseController
{
private readonly ILibrary _library;
public BooksController(ILibrary library)
private readonly IBooksHandler _handler;
public BooksController(IBooksHandler handler)
: base()
{
_library = library;
_handler = handler;
}
#region SEARCH
@ -29,53 +26,14 @@ namespace BukiVedi.App.Controllers
/// <param name="request">Поисковый запрос</param>
/// <returns>Список найденных книг</returns>
[HttpPost("search")]
public async Task<ActionResult<IEnumerable<BookResponse>>> Search([FromBody] QueryRequest request)
{
if (string.IsNullOrWhiteSpace(request.Query) == false)
{
switch (request.Query.Trim().ToLowerInvariant())
{
case "@favorites":
{
var books = (await _library.SearchFavoritesBooks(OperationContext.OperationInitiator.Id)).ToArray();
return Ok(await BookEntityMapper.Map(books));
}
case "@favoriteauthors":
{
var books = (await _library.SearchFavoriteAuthorsBooks(OperationContext.OperationInitiator.Id)).ToArray();
return Ok(await BookEntityMapper.Map(books));
}
case "@tagged":
public async Task<ActionResult<IEnumerable<BookInfo>>> Search([FromBody] QueryRequest request)
{
string tag = null;
if (Request.Query.TryGetValue("tag", out var sv))
{
tag = sv.ToString();
}
var books = (await _library.SearchTaggedBooks(OperationContext.OperationInitiator.Id, tag: tag!)).ToArray();
return Ok(await BookEntityMapper.Map(books));
}
case "@blocked":
{
var books = (await _library.SearchBlockedBooks(OperationContext.OperationInitiator.Id)).ToArray();
return Ok(await BookEntityMapper.Map(books));
}
case "@toread":
{
var books = (await _library.SearchToReadBooks(OperationContext.OperationInitiator.Id)).ToArray();
return Ok(await BookEntityMapper.Map(books));
}
default:
{
var books = (await _library.SearchBooks(request.Query)).ToArray();
return Ok(await BookEntityMapper.Map(books));
}
}
}
return Ok(Enumerable.Empty<BookResponse>());
return Ok(await _handler.Search(request.Query, tag, OperationContext));
}
#endregion
@ -87,22 +45,7 @@ namespace BukiVedi.App.Controllers
[HttpPost("{id}/favorite")]
public async Task<IActionResult> AddToFavorite([FromRoute] string id)
{
if (await Tables.Books.ExistById(id))
{
var account_id = OperationContext.OperationInitiator.Id;
if (!string.IsNullOrEmpty(account_id))
{
var exists_fiter = Builders<FavoriteBook>.Filter.And
(
Builders<FavoriteBook>.Filter.Eq(f => f.UserId, account_id),
Builders<FavoriteBook>.Filter.Eq(f => f.BookId, id)
);
if (await Tables.FavoriteBooks.Exists(exists_fiter) == false)
{
await Tables.FavoriteBooks.Write(new FavoriteBook { BookId = id, UserId = account_id });
}
}
}
await _handler.AddToFavorite(id, OperationContext);
return Ok();
}
@ -114,27 +57,7 @@ namespace BukiVedi.App.Controllers
[HttpPost("{id}/authors/favorite")]
public async Task<IActionResult> AddAuthorsToFavorite([FromRoute] string id)
{
var book = await Tables.Books.GetById(id);
if (book != null)
{
var account_id = OperationContext.OperationInitiator.Id;
var authors = book.AuthorIds;
if (!string.IsNullOrEmpty(account_id) && authors?.Count > 0)
{
foreach (var author in authors)
{
var exists_fiter = Builders<FavoriteAuthor>.Filter.And
(
Builders<FavoriteAuthor>.Filter.Eq(f => f.UserId, account_id),
Builders<FavoriteAuthor>.Filter.Eq(f => f.AuthorId, author)
);
if (await Tables.FavoriteAuthors.Exists(exists_fiter) == false)
{
await Tables.FavoriteAuthors.Write(new FavoriteAuthor { AuthorId = author, UserId = account_id });
}
}
}
}
await _handler.AddAuthorsToFavorite(id, OperationContext);
return Ok();
}
@ -146,22 +69,7 @@ namespace BukiVedi.App.Controllers
[HttpPost("{id}/block")]
public async Task<IActionResult> BlockBook([FromRoute] string id)
{
if (await Tables.Books.ExistById(id))
{
var account_id = OperationContext.OperationInitiator.Id;
if (!string.IsNullOrEmpty(account_id))
{
var exists_fiter = Builders<DisgustingBook>.Filter.And
(
Builders<DisgustingBook>.Filter.Eq(f => f.UserId, account_id),
Builders<DisgustingBook>.Filter.Eq(f => f.BookId, id)
);
if (await Tables.DisgustingBooks.Exists(exists_fiter) == false)
{
await Tables.DisgustingBooks.Write(new DisgustingBook { BookId = id, UserId = account_id });
}
}
}
await _handler.BlockBook(id, OperationContext);
return Ok();
}
@ -171,29 +79,9 @@ namespace BukiVedi.App.Controllers
/// <param name="id">Идентификатор книги, чьих авторов нужно заблокировать</param>
/// <returns>Ok</returns>
[HttpPost("{id}/author/block")]
public async Task<ActionResult<IEnumerable<BookResponse>>> BlockBookAuthor([FromRoute] string id)
{
var book = await Tables.Books.GetById(id);
if (book != null)
{
var account_id = OperationContext.OperationInitiator.Id;
var authors = book.AuthorIds;
if (!string.IsNullOrEmpty(account_id) && authors?.Count > 0)
{
foreach (var author in authors)
public async Task<ActionResult> BlockBookAuthor([FromRoute] string id)
{
var exists_fiter = Builders<DisgustingAuthor>.Filter.And
(
Builders<DisgustingAuthor>.Filter.Eq(f => f.UserId, account_id),
Builders<DisgustingAuthor>.Filter.Eq(f => f.AuthorId, author)
);
if (await Tables.DisgustingAuthors.Exists(exists_fiter) == false)
{
await Tables.DisgustingAuthors.Write(new DisgustingAuthor { AuthorId = author, UserId = account_id });
}
}
}
}
await _handler.BlockBookAuthor(id, OperationContext);
return Ok();
}
@ -205,22 +93,7 @@ namespace BukiVedi.App.Controllers
[HttpPost("{id}/read")]
public async Task<IActionResult> AddBookToReadingQueue([FromRoute] string id)
{
if (await Tables.Books.ExistById(id))
{
var account_id = OperationContext.OperationInitiator.Id;
if (!string.IsNullOrEmpty(account_id))
{
var exists_fiter = Builders<ReadQueueItem>.Filter.And
(
Builders<ReadQueueItem>.Filter.Eq(f => f.UserId, account_id),
Builders<ReadQueueItem>.Filter.Eq(f => f.BookId, id)
);
if (await Tables.ReadQueue.Exists(exists_fiter) == false)
{
await Tables.ReadQueue.Write(new ReadQueueItem { BookId = id, UserId = account_id, Timestamp = Timestamp.UtcNow });
}
}
}
await _handler.AddBookToReadingQueue(id, OperationContext);
return Ok();
}
@ -232,12 +105,43 @@ namespace BukiVedi.App.Controllers
[HttpGet("download/{id}")]
public async Task<IActionResult> GetBlobDownload([FromRoute] string id)
{
var content = new System.IO.MemoryStream();
await _library.DownloadToStream(content, id);
content.Position = 0;
var (name, content) = await _handler.GetBlobData(id, OperationContext);
var contentType = "APPLICATION/octet-stream";
var fileName = $"{id}.fb2";
var fileName = $"{name}.fb2";
return File(content, contentType, fileName);
}
/// <summary>
/// Удаление книги из избранного
/// </summary>
/// <returns>Ok</returns>
[HttpDelete("{id}/favorite")]
public async Task<ActionResult<bool>> RemoveFromFavorites([FromRoute] string id)
{
await _handler.RemoveFromFavorite(id, OperationContext);
return Ok();
}
/// <summary>
/// Удаление книги из заблокированных
/// </summary>
/// <returns>Ok</returns>
[HttpDelete("{id}/block")]
public async Task<ActionResult<bool>> Unblock([FromRoute] string id)
{
await _handler.UnblockBook(id, OperationContext);
return Ok();
}
/// <summary>
/// Удаление книги из очереди на чтение
/// </summary>
/// <returns>Ok</returns>
[HttpDelete("{id}/read")]
public async Task<ActionResult<bool>> RemoveFromReadingQueue([FromRoute] string id)
{
await _handler.RemoveFromReadingQueue(id, OperationContext);
return Ok();
}
}
}

@ -1,11 +1,8 @@
using BukiVedi.App.Requests;
using BukiVedi.App.Responces;
using BukiVedi.App.Services.Mappers;
using BukiVedi.Shared.Entities;
using BukiVedi.Shared.Services;
using BukiVedi.Shared.Apps;
using BukiVedi.Shared.Models;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using MongoDB.Driver;
namespace BukiVedi.App.Controllers
{
@ -15,69 +12,52 @@ namespace BukiVedi.App.Controllers
public class TagsController
: BaseController
{
private readonly ILibrary _library;
public TagsController(ILibrary library)
private readonly ITagsHandler _handler;
public TagsController(ITagsHandler handler)
: base()
{
_library = library;
_handler = handler;
}
/// <summary>
/// Добавление тега для книги
/// Список пользовательских тегов
/// </summary>
/// <returns>Ok</returns>
[HttpPost]
public async Task<IActionResult> AppendTag([FromBody] AppendTagRequest request)
{
if (request != null && string.IsNullOrWhiteSpace(request.Name) == false && await Tables.Books.ExistById(request.BookId))
{
var name = request.Name.Trim().ToLowerInvariant();
var tagFilter = Builders<UserTag>.Filter.And(Builders<UserTag>.Filter.Eq(t => t.BookId, request.BookId), Builders<UserTag>.Filter.Eq(t => t.Name, name));
if (false == await Tables.UserTag.Exists(tagFilter))
/// <returns></returns>
[HttpGet]
public async Task<ActionResult<IEnumerable<string>>> GetUserTags()
{
await Tables.UserTag.Write(new UserTag { BookId = request.BookId, Name = name, UserId = OperationContext.OperationInitiator.Id });
}
}
return Ok();
return Ok(await _handler.GetUserTags(OperationContext));
}
/// <summary>
/// Удаление тега для книги
/// Добавление тега для книги
/// </summary>
/// <returns>Ok</returns>
[HttpDelete("id")]
public async Task<ActionResult<bool>> RemoveTag([FromRoute] string id)
{
if (string.IsNullOrWhiteSpace(id) == false && await Tables.UserTag.ExistById(id))
[HttpPost]
public async Task<IActionResult> AppendTag([FromBody] AppendTagRequest request)
{
return Ok(await Tables.UserTag.TryRemoveById(id));
}
return Ok(false);
await _handler.AppendTag(request?.BookId!, request?.Name!, OperationContext);
return Ok();
}
/// <summary>
/// Список пользовательских тегов
/// Поиск книг по тегу
/// </summary>
/// <returns></returns>
[HttpGet]
public async Task<ActionResult<IEnumerable<string>>> GetUserTags()
/// <returns>Список найденных книг</returns>
[HttpPost("{id}/books")]
public async Task<ActionResult<IEnumerable<BookInfo>>> Search([FromRoute] string id)
{
return Ok((await Tables.UserTag.Get(Builders<UserTag>.Filter.Eq(t => t.UserId, OperationContext.OperationInitiator.Id)))?.Select(t => t.Name));
return Ok(await _handler.Search(id, OperationContext));
}
/// <summary>
/// Поиск книг по тегу
/// Удаление тега для книги
/// </summary>
/// <returns>Список найденных книг</returns>
[HttpPost("{id}/books")]
public async Task<ActionResult<IEnumerable<BookResponse>>> Search([FromRoute] string id)
{
if (string.IsNullOrWhiteSpace(id) == false)
/// <returns>Ok</returns>
[HttpDelete("{id}")]
public async Task<ActionResult<bool>> RemoveTag([FromRoute] string id)
{
var books = await _library.SearchByTagBooks(OperationContext.OperationInitiator.Id, id);
return Ok(await BookEntityMapper.Map(books));
}
return Ok(Enumerable.Empty<BookResponse>());
return Ok(await _handler.RemoveTag(id, OperationContext));
}
}
}

@ -1,5 +1,6 @@
using BukiVedi.App.Middlewares;
using BukiVedi.Shared;
using BukiVedi.Shared.Apps;
using BukiVedi.Shared.Entities;
using BukiVedi.Shared.Services;
using Microsoft.AspNetCore.Authentication.Cookies;
@ -91,8 +92,13 @@ namespace BukiVedi.App
{
await authProvider.CreateAccount(platformAdmin);
}
var library = new Library();
services.AddSingleton<IAuthProvider>(authProvider);
services.AddSingleton<ILibrary>(new Library());
services.AddSingleton<ILibrary>(library);
services.AddSingleton<IAuthorHandler>(new AuthorHandler(library));
services.AddSingleton<ITagsHandler>(new TagsHandler(library));
services.AddSingleton<IBooksHandler>(new BooksHandler(library));
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie(o =>
{
o.LoginPath = new PathString("/web/login.html");

@ -5,7 +5,7 @@ https://go.microsoft.com/fwlink/?LinkID=208121.
<Project>
<PropertyGroup>
<_PublishTargetUrl>G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Release\net8.0\publish\</_PublishTargetUrl>
<History>True|2024-04-28T14:30:08.5715518Z;True|2024-04-28T17:28:06.6959908+03:00;True|2024-04-28T16:38:39.9281743+03:00;False|2024-04-28T16:36:56.3567692+03:00;False|2024-04-28T16:36:21.9546945+03:00;False|2024-04-28T16:35:24.2096595+03:00;True|2024-04-09T13:52:12.7238098+03:00;True|2024-04-07T21:16:45.6816851+03:00;True|2024-04-07T05:01:48.6765910+03:00;True|2024-04-07T05:01:36.8953339+03:00;True|2024-04-07T04:57:19.2521218+03:00;True|2024-04-06T21:11:57.8349210+03:00;True|2024-04-06T17:36:58.3428821+03:00;True|2024-04-05T04:52:06.7814045+03:00;True|2024-04-05T04:46:11.3960475+03:00;True|2024-04-04T16:59:14.8807703+03:00;True|2024-04-04T14:55:51.0062074+03:00;True|2024-04-04T14:01:53.0402462+03:00;True|2024-04-04T05:50:10.9326327+03:00;True|2024-04-04T05:23:22.3837261+03:00;True|2024-04-04T05:18:08.8436345+03:00;True|2024-04-04T05:13:03.4261357+03:00;True|2024-04-04T04:23:59.4217155+03:00;True|2024-04-04T04:12:10.2381826+03:00;True|2024-04-04T04:04:27.2386390+03:00;</History>
<History>True|2024-05-12T17:17:18.3446630Z;True|2024-05-12T20:11:53.1976666+03:00;True|2024-04-28T17:30:08.5715518+03:00;True|2024-04-28T17:28:06.6959908+03:00;True|2024-04-28T16:38:39.9281743+03:00;False|2024-04-28T16:36:56.3567692+03:00;False|2024-04-28T16:36:21.9546945+03:00;False|2024-04-28T16:35:24.2096595+03:00;True|2024-04-09T13:52:12.7238098+03:00;True|2024-04-07T21:16:45.6816851+03:00;True|2024-04-07T05:01:48.6765910+03:00;True|2024-04-07T05:01:36.8953339+03:00;True|2024-04-07T04:57:19.2521218+03:00;True|2024-04-06T21:11:57.8349210+03:00;True|2024-04-06T17:36:58.3428821+03:00;True|2024-04-05T04:52:06.7814045+03:00;True|2024-04-05T04:46:11.3960475+03:00;True|2024-04-04T16:59:14.8807703+03:00;True|2024-04-04T14:55:51.0062074+03:00;True|2024-04-04T14:01:53.0402462+03:00;True|2024-04-04T05:50:10.9326327+03:00;True|2024-04-04T05:23:22.3837261+03:00;True|2024-04-04T05:18:08.8436345+03:00;True|2024-04-04T05:13:03.4261357+03:00;True|2024-04-04T04:23:59.4217155+03:00;True|2024-04-04T04:12:10.2381826+03:00;True|2024-04-04T04:04:27.2386390+03:00;</History>
<LastFailureDetails />
</PropertyGroup>
</Project>

@ -1,77 +1,4 @@
namespace BukiVedi.App.Responces
{
public class AuthorInfo
{
public string Id { get; set; }
public string Name { get; set; }
}
public class GenreInfo
{
public string Id { get; set; }
public string Name { get; set; }
}
public class TagInfo
{
public string Id { get; set; }
public string Name { get; set; }
}
public class FormatInfo
{
public string Id { get; set; }
public string Name { get; set; }
}
public class BookResponse
{
/// <summary>
/// Идентификатор
/// </summary>
public string Id { get; set; }
/// <summary>
/// Изображение(урл)
/// </summary>
public string ImageUrl { get; set; }
/// <summary>
/// Название
/// </summary>
public string Title { get; set; }
/// <summary>
/// Описание
/// </summary>
public string Description { get; set; }
/// <summary>
/// Заметка
/// </summary>
public string Note { get; set; }
/// <summary>
/// Авторы(массив объектов с полями id; имя автора)
/// </summary>
public AuthorInfo[] Authors { get; set; }
/// <summary>
/// Жанры(массив объектов с полями id; название жанра)
/// </summary>
public GenreInfo[] Genres { get; set; }
/// <summary>
/// Серия
/// </summary>
public string Series { get; set; }
/// <summary>
/// Подсерия
/// </summary>
public string Subseries { get; set; }
/// <summary>
/// Теги(массив объектов с полями id; имя тега)
/// </summary>
public IEnumerable<TagInfo> Tags { get; set; }
/// <summary>
/// Год издания
/// </summary>
public int Year { get; set; }
public string Format { get; set; }
public bool IsBlocked { get; set; }
public bool IsFavorite { get; set; }
}
}

@ -1,5 +1,5 @@
using BukiVedi.App.Responces;
using BukiVedi.Shared.Entities;
using BukiVedi.Shared.Entities;
using BukiVedi.Shared.Models;
using BukiVedi.Shared.Services;
using MongoDB.Driver;
@ -7,7 +7,7 @@ namespace BukiVedi.App.Services.Mappers
{
public class BookEntityMapper
{
public static async Task<IEnumerable<BookResponse>> Map(IEnumerable<BookEntity> books)
public static async Task<IEnumerable<BookInfo>> Map(IEnumerable<BookEntity> books)
{
var booksIds = books.Select(x => x.Id).ToList();
var tags_list = (await Tables.UserTag.Get(Builders<UserTag>.Filter.In(t => t.BookId, booksIds)));
@ -26,7 +26,7 @@ namespace BukiVedi.App.Services.Mappers
}
return books.Select(book =>
new BookResponse
new BookInfo
{
Authors = book.Authors.Select(a => new AuthorInfo { Id = a.Id, Name = a.Name }).ToArray(),
Description = book.Description,

@ -5,7 +5,7 @@
},
"projects": {
"F:\\Documents\\GitHub\\Zero\\ZeroLevel\\ZeroLevel.csproj": {
"version": "1.0.0",
"version": "4.0.0",
"restore": {
"projectUniqueName": "F:\\Documents\\GitHub\\Zero\\ZeroLevel\\ZeroLevel.csproj",
"projectName": "ZeroLevel",

@ -14,7 +14,7 @@ using System.Reflection;
[assembly: System.Reflection.AssemblyCompanyAttribute("BukiVedi.App")]
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+653045cfe4c19cb8cabc63ce1b8f61d4b7e4f26e")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+431f2503a837ccf39eac97076a865db39f86a8dd")]
[assembly: System.Reflection.AssemblyProductAttribute("BukiVedi.App")]
[assembly: System.Reflection.AssemblyTitleAttribute("BukiVedi.App")]
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]

@ -1 +1 @@
9daab03e895a6f115233529b5b412c23d0bcacc1749fa577a062fe4da0d423fa
7f90fe300e225561cd7cc7726bf5d2f940d1cc60e07ec84b3e5f3a0ec108d1d7

@ -1,11 +1,5 @@
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Debug\net8.0\appsettings.Development.json
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Debug\net8.0\appsettings.json
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Debug\net8.0\web\css\fonts\Roboto-300.ttf
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Debug\net8.0\web\css\fonts\Roboto-300.woff
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Debug\net8.0\web\css\fonts\Roboto-300.woff2
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Debug\net8.0\web\css\fonts\Roboto-400.ttf
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Debug\net8.0\web\css\fonts\Roboto-400.woff
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Debug\net8.0\web\css\fonts\Roboto-400.woff2
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Debug\net8.0\web\images\favicon.ico
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Debug\net8.0\BukiVedi.App.exe
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Debug\net8.0\config.ini
@ -18,11 +12,6 @@ G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Debug\net8.0\web\css\main.css
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Debug\net8.0\web\css\normalize.css
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Debug\net8.0\web\images\flower.jpeg
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Debug\net8.0\web\index.html
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Debug\net8.0\web\js\common\jquery.js
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Debug\net8.0\web\js\constants\index.js
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Debug\net8.0\web\js\login\index.js
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Debug\net8.0\web\js\main\index.js
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Debug\net8.0\web\js\requests\index.js
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Debug\net8.0\web\login.html
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Debug\net8.0\BukiVedi.App.deps.json
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Debug\net8.0\BukiVedi.App.runtimeconfig.json
@ -76,5 +65,20 @@ G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\obj\Debug\net8.0\refint\BukiVedi.A
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\obj\Debug\net8.0\BukiVedi.App.pdb
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\obj\Debug\net8.0\BukiVedi.App.genruntimeconfig.cache
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\obj\Debug\net8.0\ref\BukiVedi.App.dll
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Debug\net8.0\web\assets\heart.svg
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Debug\net8.0\web\assets\heart_full.svg
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Debug\net8.0\web\css\scroll.css
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Debug\net8.0\web\fonts\Roboto-Black.ttf
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Debug\net8.0\web\fonts\Roboto-BlackItalic.ttf
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Debug\net8.0\web\fonts\Roboto-Bold.ttf
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Debug\net8.0\web\fonts\Roboto-BoldItalic.ttf
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Debug\net8.0\web\fonts\Roboto-Italic.ttf
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Debug\net8.0\web\fonts\Roboto-Light.ttf
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Debug\net8.0\web\fonts\Roboto-LightItalic.ttf
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Debug\net8.0\web\fonts\Roboto-Medium.ttf
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Debug\net8.0\web\fonts\Roboto-MediumItalic.ttf
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Debug\net8.0\web\fonts\Roboto-Regular.ttf
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Debug\net8.0\web\fonts\Roboto-Thin.ttf
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Debug\net8.0\web\fonts\Roboto-ThinItalic.ttf
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Debug\net8.0\LemmaSharpPrebuilt.pdb
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Debug\net8.0\LemmaSharpPrebuilt.dll.config

@ -14,7 +14,7 @@ using System.Reflection;
[assembly: System.Reflection.AssemblyCompanyAttribute("BukiVedi.App")]
[assembly: System.Reflection.AssemblyConfigurationAttribute("Release")]
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+653045cfe4c19cb8cabc63ce1b8f61d4b7e4f26e")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+431f2503a837ccf39eac97076a865db39f86a8dd")]
[assembly: System.Reflection.AssemblyProductAttribute("BukiVedi.App")]
[assembly: System.Reflection.AssemblyTitleAttribute("BukiVedi.App")]
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]

@ -1 +1 @@
fdd5f880a586f54d63e65e077bb04d3db4265027ab5434a4a34588cbd432d5ad
731a41efb4470858e97b70db5c6c673a43866001a9d9b8ac769cdb5c62d8eec0

@ -6,12 +6,6 @@ G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\obj\Release\net8.0\BukiVedi.App.cs
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\obj\Release\net8.0\BukiVedi.App.MvcApplicationPartsAssemblyInfo.cache
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Release\net8.0\appsettings.Development.json
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Release\net8.0\appsettings.json
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Release\net8.0\web\css\fonts\Roboto-300.ttf
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Release\net8.0\web\css\fonts\Roboto-300.woff
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Release\net8.0\web\css\fonts\Roboto-300.woff2
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Release\net8.0\web\css\fonts\Roboto-400.ttf
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Release\net8.0\web\css\fonts\Roboto-400.woff
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Release\net8.0\web\css\fonts\Roboto-400.woff2
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Release\net8.0\web\images\favicon.ico
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Release\net8.0\BukiVedi.App.exe
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Release\net8.0\config.ini
@ -24,11 +18,6 @@ G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Release\net8.0\web\css\main.cs
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Release\net8.0\web\css\normalize.css
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Release\net8.0\web\images\flower.jpeg
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Release\net8.0\web\index.html
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Release\net8.0\web\js\common\jquery.js
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Release\net8.0\web\js\constants\index.js
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Release\net8.0\web\js\login\index.js
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Release\net8.0\web\js\main\index.js
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Release\net8.0\web\js\requests\index.js
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Release\net8.0\web\login.html
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Release\net8.0\BukiVedi.App.deps.json
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Release\net8.0\BukiVedi.App.runtimeconfig.json
@ -77,3 +66,25 @@ G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\obj\Release\net8.0\refint\BukiVedi
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\obj\Release\net8.0\BukiVedi.App.pdb
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\obj\Release\net8.0\BukiVedi.App.genruntimeconfig.cache
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\obj\Release\net8.0\ref\BukiVedi.App.dll
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Release\net8.0\web\assets\heart.svg
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Release\net8.0\web\assets\heart_full.svg
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Release\net8.0\web\css\scroll.css
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Release\net8.0\web\fonts\Roboto-Black.ttf
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Release\net8.0\web\fonts\Roboto-BlackItalic.ttf
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Release\net8.0\web\fonts\Roboto-Bold.ttf
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Release\net8.0\web\fonts\Roboto-BoldItalic.ttf
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Release\net8.0\web\fonts\Roboto-Italic.ttf
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Release\net8.0\web\fonts\Roboto-Light.ttf
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Release\net8.0\web\fonts\Roboto-LightItalic.ttf
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Release\net8.0\web\fonts\Roboto-Medium.ttf
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Release\net8.0\web\fonts\Roboto-MediumItalic.ttf
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Release\net8.0\web\fonts\Roboto-Regular.ttf
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Release\net8.0\web\fonts\Roboto-Thin.ttf
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Release\net8.0\web\fonts\Roboto-ThinItalic.ttf
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Release\net8.0\web\js\common\jquery.js
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Release\net8.0\web\js\constants\index.js
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Release\net8.0\web\js\login\index.js
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Release\net8.0\web\js\main\index.js
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Release\net8.0\web\js\requests\index.js
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Release\net8.0\web\js\scroll\index.js
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Release\net8.0\web\script.js

@ -312,7 +312,7 @@
"LemmaSharpPrebuiltFull": "1.0.0",
"MongoDB.Driver": "2.24.0",
"Sleopok.Engine": "1.0.0",
"ZeroLevel": "1.0.0"
"ZeroLevel": "4.0.0"
},
"compile": {
"bin/placeholder/BukiVedi.Shared.dll": {}
@ -359,7 +359,7 @@
"type": "project",
"framework": ".NETCoreApp,Version=v8.0",
"dependencies": {
"ZeroLevel": "1.0.0"
"ZeroLevel": "4.0.0"
},
"compile": {
"bin/placeholder/Sleopok.Engine.dll": {}
@ -368,7 +368,7 @@
"bin/placeholder/Sleopok.Engine.dll": {}
}
},
"ZeroLevel/1.0.0": {
"ZeroLevel/4.0.0": {
"type": "project",
"framework": ".NETStandard,Version=v2.1",
"compile": {
@ -901,7 +901,7 @@
"path": "../../../sleopok/src/Sleopok/Sleopok.Engine/Sleopok.Engine.csproj",
"msbuildProject": "../../../sleopok/src/Sleopok/Sleopok.Engine/Sleopok.Engine.csproj"
},
"ZeroLevel/1.0.0": {
"ZeroLevel/4.0.0": {
"type": "project",
"path": "F:\\Documents\\GitHub\\Zero\\ZeroLevel\\ZeroLevel.csproj",
"msbuildProject": "F:\\Documents\\GitHub\\Zero\\ZeroLevel\\ZeroLevel.csproj"

@ -1,6 +1,6 @@
{
"version": 2,
"dgSpecHash": "khX5RP6JJFT2LBLzj+Ot4o0IXXnuCqfW0ZG0t4xzjbbr+k4RiF1Ho6zHhDdd5SOV8/ypGBf2EKTEXhGJLWyDqw==",
"dgSpecHash": "cgT03nZvFhiSJWavUt+O9IWjN5VoS+X4EMqHGR07TZbMsT+VDQcLTRikmEXkuWgt3Qvgp/8+UNd1Imh81KhCvQ==",
"success": true,
"projectFilePath": "G:\\Documents\\GitHub\\BukiVedi\\src\\BukiVedi.App\\BukiVedi.App.csproj",
"expectedPackageFiles": [
@ -22,7 +22,8 @@
"C:\\Users\\Ogoun\\.nuget\\packages\\system.runtime.compilerservices.unsafe\\5.0.0\\system.runtime.compilerservices.unsafe.5.0.0.nupkg.sha512",
"C:\\Users\\Ogoun\\.nuget\\packages\\system.security.accesscontrol\\5.0.0\\system.security.accesscontrol.5.0.0.nupkg.sha512",
"C:\\Users\\Ogoun\\.nuget\\packages\\system.security.principal.windows\\5.0.0\\system.security.principal.windows.5.0.0.nupkg.sha512",
"C:\\Users\\Ogoun\\.nuget\\packages\\zstdsharp.port\\0.7.3\\zstdsharp.port.0.7.3.nupkg.sha512"
"C:\\Users\\Ogoun\\.nuget\\packages\\zstdsharp.port\\0.7.3\\zstdsharp.port.0.7.3.nupkg.sha512",
"C:\\Users\\Ogoun\\.nuget\\packages\\zerolevel\\4.0.0\\zerolevel.4.0.0.nupkg.sha512"
],
"logs": []
}

@ -5,7 +5,7 @@
},
"projects": {
"F:\\Documents\\GitHub\\Zero\\ZeroLevel\\ZeroLevel.csproj": {
"version": "1.0.0",
"version": "4.0.0",
"restore": {
"projectUniqueName": "F:\\Documents\\GitHub\\Zero\\ZeroLevel\\ZeroLevel.csproj",
"projectName": "ZeroLevel",

@ -312,7 +312,7 @@
"LemmaSharpPrebuiltFull": "1.0.0",
"MongoDB.Driver": "2.24.0",
"Sleopok.Engine": "1.0.0",
"ZeroLevel": "1.0.0"
"ZeroLevel": "4.0.0"
},
"compile": {
"bin/placeholder/BukiVedi.Shared.dll": {}
@ -359,7 +359,7 @@
"type": "project",
"framework": ".NETCoreApp,Version=v8.0",
"dependencies": {
"ZeroLevel": "1.0.0"
"ZeroLevel": "4.0.0"
},
"compile": {
"bin/placeholder/Sleopok.Engine.dll": {}
@ -368,7 +368,7 @@
"bin/placeholder/Sleopok.Engine.dll": {}
}
},
"ZeroLevel/1.0.0": {
"ZeroLevel/4.0.0": {
"type": "project",
"framework": ".NETStandard,Version=v2.1",
"compile": {
@ -657,7 +657,7 @@
"LemmaSharpPrebuiltFull": "1.0.0",
"MongoDB.Driver": "2.24.0",
"Sleopok.Engine": "1.0.0",
"ZeroLevel": "1.0.0"
"ZeroLevel": "4.0.0"
},
"compile": {
"bin/placeholder/BukiVedi.Shared.dll": {}
@ -704,7 +704,7 @@
"type": "project",
"framework": ".NETCoreApp,Version=v8.0",
"dependencies": {
"ZeroLevel": "1.0.0"
"ZeroLevel": "4.0.0"
},
"compile": {
"bin/placeholder/Sleopok.Engine.dll": {}
@ -713,7 +713,7 @@
"bin/placeholder/Sleopok.Engine.dll": {}
}
},
"ZeroLevel/1.0.0": {
"ZeroLevel/4.0.0": {
"type": "project",
"framework": ".NETStandard,Version=v2.1",
"compile": {
@ -1246,7 +1246,7 @@
"path": "../../../sleopok/src/Sleopok/Sleopok.Engine/Sleopok.Engine.csproj",
"msbuildProject": "../../../sleopok/src/Sleopok/Sleopok.Engine/Sleopok.Engine.csproj"
},
"ZeroLevel/1.0.0": {
"ZeroLevel/4.0.0": {
"type": "project",
"path": "F:\\Documents\\GitHub\\Zero\\ZeroLevel\\ZeroLevel.csproj",
"msbuildProject": "F:\\Documents\\GitHub\\Zero\\ZeroLevel\\ZeroLevel.csproj"

@ -1,6 +1,6 @@
{
"version": 2,
"dgSpecHash": "YieecpqSbR1Q03HaeUp2CKgHkYXxRAAhOAbWwh8Y/r3bb53xP809lSyjzaaR59H8XIbINJ6PeUVYKgglvcHt4w==",
"dgSpecHash": "WT8+/bOG0gQIp6FInML/Lmsskjf0rg/5st9Dd3VHXhEoUwL33AGiTDPmzKYmwAabUxVLuUF2b5V0y6nxXgGKEg==",
"success": true,
"projectFilePath": "G:\\Documents\\GitHub\\BukiVedi\\src\\BukiVedi.App\\BukiVedi.App.csproj",
"expectedPackageFiles": [
@ -23,6 +23,7 @@
"C:\\Users\\Ogoun\\.nuget\\packages\\system.security.accesscontrol\\5.0.0\\system.security.accesscontrol.5.0.0.nupkg.sha512",
"C:\\Users\\Ogoun\\.nuget\\packages\\system.security.principal.windows\\5.0.0\\system.security.principal.windows.5.0.0.nupkg.sha512",
"C:\\Users\\Ogoun\\.nuget\\packages\\zstdsharp.port\\0.7.3\\zstdsharp.port.0.7.3.nupkg.sha512",
"C:\\Users\\Ogoun\\.nuget\\packages\\zerolevel\\4.0.0\\zerolevel.4.0.0.nupkg.sha512",
"C:\\Users\\Ogoun\\.nuget\\packages\\microsoft.netcore.app.runtime.linux-x64\\8.0.4\\microsoft.netcore.app.runtime.linux-x64.8.0.4.nupkg.sha512",
"C:\\Users\\Ogoun\\.nuget\\packages\\microsoft.aspnetcore.app.runtime.linux-x64\\8.0.4\\microsoft.aspnetcore.app.runtime.linux-x64.8.0.4.nupkg.sha512",
"C:\\Users\\Ogoun\\.nuget\\packages\\microsoft.netcore.app.host.linux-x64\\8.0.4\\microsoft.netcore.app.host.linux-x64.8.0.4.nupkg.sha512"

@ -0,0 +1,16 @@
<svg width="20px" height="20px" viewBox="0 0 32 32" enable-background="new 0 0 32 32" id="Stock_cut" version="1.1" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="SVGRepo_bgCarrier" stroke-width="0"/>
<g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"/>
<g id="SVGRepo_iconCarrier">
<desc/>
<path d="M28.343,17.48L16,29 L3.657,17.48C1.962,15.898,1,13.684,1,11.365v0C1,6.745,4.745,3,9.365,3h0.17c2.219,0,4.346,0.881,5.915,2.45L16,6l0.55-0.55 C18.119,3.881,20.246,3,22.465,3h0.17C27.255,3,31,6.745,31,11.365v0C31,13.684,30.038,15.898,28.343,17.48z" fill="#fff" stroke="#000" stroke-linejoin="round" stroke-miterlimit="10" stroke-width="2"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 744 B

@ -0,0 +1,16 @@
<svg width="20px" height="20px" viewBox="0 0 32 32" enable-background="new 0 0 32 32" id="Stock_cut" version="1.1" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="SVGRepo_bgCarrier" stroke-width="0"/>
<g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"/>
<g id="SVGRepo_iconCarrier">
<desc/>
<path d="M28.343,17.48L16,29 L3.657,17.48C1.962,15.898,1,13.684,1,11.365v0C1,6.745,4.745,3,9.365,3h0.17c2.219,0,4.346,0.881,5.915,2.45L16,6l0.55-0.55 C18.119,3.881,20.246,3,22.465,3h0.17C27.255,3,31,6.745,31,11.365v0C31,13.684,30.038,15.898,28.343,17.48z" fill="#FF748F" stroke="#FF748F" stroke-linejoin="round" stroke-miterlimit="10" stroke-width="2"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 750 B

@ -47,6 +47,7 @@ input {
--second-font-color: #bfbfbf;
--active-color: #2173e0;
--matte-white: #f2f3f4;
--accent-color: #FF748F;
}
/***
@ -126,6 +127,10 @@ input {
display: flex;
}
.d-bl {
display: block;
}
/**
headings and texts
*/

@ -1,7 +1,7 @@
.background-logo {
position: absolute;
top: 26px;
top: -15px;
left: 20px;
z-index: -1;
overflow: hidden;

@ -4,6 +4,7 @@ body {
}
body {
position: relative;
margin: 0px;
padding: 0px;
width: 100%;
@ -12,6 +13,10 @@ body {
background-color: var(--main-bg-color);
}
header {
position: relative;
}
.main-search-wrapper {
position: relative;
max-width: 820px;
@ -117,8 +122,9 @@ body {
}
.blur > .flowers {
filter: blur(2px);
opacity: 0.55;
background-image: none;
/* filter: blur(2px);
opacity: 0.55; */
}
.main-book__card {
@ -188,6 +194,7 @@ body {
.main-book__header {
text-overflow: ellipsis;
overflow: hidden;
padding-right: 65px;
}
.main-book__menu {
@ -227,6 +234,13 @@ body {
}
}
.main-book__menu_opened {
z-index: 2;
border-radius: 12px;
box-shadow: 0px 10px 20px 2px rgba(0, 0, 0, 0.25);
}
.main-book__menu_closed {
width: 50px;
}
@ -240,14 +254,45 @@ body {
color: var(--active-color);
}
.main-book__menu_like {
background-image: url(../web/assets/heart.svg);
background-repeat: no-repeat;
position: absolute;
width: 20px;
height: 100%;
right: 105px;
top: 20px;
cursor: pointer;
}
.main-book__menu_like:hover {
opacity: 0.5;
}
.main-book__menu_like.liked {
background-image: url(../web/assets/heart_full.svg);
}
.main-book__action {
padding-left: 12px;
padding-top: 4px;
padding-bottom: 4px;
background: #fff;
line-height: 28px;
width: 200px;
vertical-align: middle;
}
.main-book__action:first-child {
border-top-left-radius: 12px;
border-top-right-radius: 12px;
}
.main-book__action:last-child {
border-bottom-left-radius: 12px;
border-bottom-right-radius: 12px;
}
.main-book__action:hover {
background: var(--main-bg-color);
}

@ -0,0 +1,40 @@
.scroll-top {
position: fixed;
z-index: 3;
padding: 0;
right: 20px;
bottom: 20px;
opacity: 1;
visibility: hidden;
transform: translateY(0px);
height: 46px;
width: 46px;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
border-radius: 50%;
transition: all 0.4s ease;
border: none;
box-shadow: inset 0 0 0 2px var(--accent-color);
color: var(--accent-color);
background-color: #fff;
}
.scroll-top.is-active {
visibility: visible;
}
.scroll-top .icon-tabler-arrow-up {
position: absolute;
stroke-width: 2px;
stroke: var(--accent-color);
}
.scroll-top:hover {
color: var(--accent-color);
}
.scroll-top:hover .icon-tabler-arrow-up {
stroke: var(--accent-color);
}

@ -1,69 +1,41 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<head>
<title>Vedi</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link rel="icon" type="image/x-icon" href="images/favicon.ico" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, maximum-scale=1.0"
/>
<meta name="viewport"
content="width=device-width, initial-scale=1.0, maximum-scale=1.0" />
<link href="css/normalize.css" rel="stylesheet" />
<link href="css/common.css" rel="stylesheet" />
<link href="css/logo.css" rel="stylesheet" />
<link href="css/main.css" rel="stylesheet" />
<link href="css/scroll.css" rel="stylesheet" />
<script src="js/common/jquery.js"></script>
</head>
</head>
<body>
<main>
<body>
<header>
<h1 class="background-logo">Vedi</h1>
<div class="main-search-wrapper mt-l d-fl">
<div class="main-search-pic"></div>
<input
id="search"
<input id="search"
class="main-search pl-l pr-s"
placeholder="Выбери книгу, и я найду для тебя похожие"
autocomplete="off"
autofocus
/>
autofocus />
</div>
<button id="searchButton" class="main-search-btn mt-m">Найти</button>
</header>
<main>
<div id="content" class="main-content mt-l">
<div id="books"></div>
</div>
</main>
<script type="module">
import BookSection from "./js/main/index.js";
const input = document.getElementById("search");
const books = document.getElementById("books");
const booksSection = new BookSection({
url: "../api/books/search",
label: "books",
});
const click = () => {
const query = document.getElementById("search").value;
if (query) {
booksSection.update({ query });
}
};
searchButton.addEventListener("click", click);
input.addEventListener("keypress", function (event) {
if (event.key === "Enter") {
click();
}
});
books.append(booksSection.element);
</script>
</body>
<script type="module" src="script.js"></script>
</body>
</html>

@ -2,11 +2,11 @@ import * as requests from '../requests/index.js';
export const SUCCESS = "success";
export const menuEnum = [
{
id: 0,
label: "В избранное",
action: requests.addBookToFavourites,
},
// {
// id: 0,
// label: "В избранное",
// action: requests.addBookToFavourites,
// },
{
id: 1,
label: "Авторов в избранное",

@ -1,5 +1,5 @@
import { menuEnum } from "../constants/index.js";
import { fetchData, downloadBook } from "../requests/index.js";
import { fetchData, downloadBook, searchByAuthor } from "../requests/index.js";
export default class BookSection {
subElements = [];
@ -28,18 +28,25 @@ export default class BookSection {
const booksListener = document.querySelector(".main-book__wrapper");
booksListener.addEventListener("click", (event) => {
let id, title;
const isLike = event.target.closest("[data-like]");
const isMenu = event.target.closest("[data-menu]");
const isAction = event.target.closest("[data-action]");
const isLink = event.target.closest("[data-link]")
const isLink = event.target.closest("[data-link]");
const isAuthor = event.target.closest("[data-author]");
switch (true) {
case !!isAction:
id = isAction.dataset.action;
const { authorid, bookid } = isAction.parentNode.parentNode.dataset || {};
const { authorid, bookid } =
isAction.parentNode.parentNode.dataset || {};
this.makeAction({ id, authorid, bookid });
break;
case !!isLike:
this.makeLike(isLike);
break;
case !!isMenu:
this.openMenu(isMenu);
@ -47,10 +54,14 @@ export default class BookSection {
case !!isLink:
id = isLink.dataset.bookid;
title = isLink.dataset.title;
let format = isLink.dataset.format.toLowerCase()
let format = isLink.dataset.format.toLowerCase();
downloadBook({ id, title, format });
break;
case !!isAuthor:
id = isAuthor.dataset.author;
this.update({ isByAuthor: true, id });
default:
this.closeMenu();
@ -76,11 +87,16 @@ export default class BookSection {
subseries,
year,
tags,
isFavorite,
}) => {
const { name, id: authorid } = authors[0] || "Неизвестно";
return `
<article data-element="card" class="main-book__card d-fl mb-m mh-auto">
<div class="main-book__menu_wrapper">
<div class="main-book__menu_wrapper d-fl">
<div class="main-book__menu_like ${
isFavorite ? "liked" : "not-liked"
}" data-like data-bookid=${id}></div>
<nav class="main-book__menu main-book__menu_closed"
data-authorid=${authorid}
data-bookid=${id}
@ -92,16 +108,18 @@ export default class BookSection {
<a class="main-book__link"
data-link
data-bookid=${id}
data-title=${(title || 'Unknown').split(' ').join('_')}
data-title=${(title || "Unknown")
.split(" ")
.join("_")}
data-format=${format}
>${format}</a>
</div>
<div>
<img src=${
<img class="d-bl" src=${
imageUrl ? imageUrl : "../web/assets/cover.jpg"
} alt="cover" style="width:80px;height:128px;">
<div class=" main-card__name second-text mt-s">
${name || ""}</div>
<a class="main-card__author main-book__link second-text mt-s" data-author=${authorid}>
${name || ""}</a>
<div class="second-text mt-s">
${year || "Год неизвестен"}</div>
</div>
@ -153,8 +171,9 @@ export default class BookSection {
}
getTags(tags) {
return (tags || []).map(({ id, name }) => {
return `<a class="main-book__tag" data-id=${id}>#${name}</a>`;
return (tags || [])
.map(({ id, name }) => {
return `<a class="main-book__tag main-book__link" data-id=${id}>#${name}</a>`;
})
.join("");
}
@ -192,13 +211,25 @@ export default class BookSection {
}
this.element.classList.remove("spinner");
this.closeMenu()
}
makeLike(element) {
const { bookid: likedBookId } = element.dataset || {};
this.makeAction({ id: 0, authorid: "", bookid: likedBookId });
element.classList.add("liked");
}
async update(params) {
this.element.classList.add("blur", "spinner");
const query = params || {};
const data = await fetchData({ query, url: this.url });
let data = [];
if (params?.isByAuthor) {
data = await searchByAuthor({ id: params.id });
} else {
const query = params;
data = await fetchData({ query, url: this.url });
}
console.log("data", data);
if (data && Object.values(data).length) {
this.subElements.body.innerHTML = this.getBookBody(data);
@ -208,6 +239,7 @@ export default class BookSection {
}
this.element.classList.remove("spinner");
}
getSubElements(element) {
const result = {};
const elements = element.querySelectorAll("[data-element]");

@ -1,6 +1,7 @@
import { SUCCESS } from "../constants/index.js";
export const fetchData = ({ query, url }) => {
console.log('query, url', query, url);
return $.ajax({
contentType: "application/json; charset=utf-8",
dataType: "json",
@ -120,3 +121,21 @@ export const downloadBook = ({ id, title, format }) => {
},
});
}
export const searchByAuthor = ({ id }) => {
return $.ajax({
contentType: "application/json; charset=utf-8",
dataType: "json",
type: "POST",
url: `../api/author/${id}/books`,
success: function (data, textStatus, jqXHR) {
if (textStatus === SUCCESS) {
return data;
}
return [];
},
error: function (jqXHR, textStatus, errorThrown) {
console.log(jqXHR.statusText);
},
});
};

@ -0,0 +1,80 @@
export default class ButtonScroll {
element;
constructor() {
this.render();
}
get template() {
return `
<button
class="btn-toggle-round scroll-top js-scroll-top"
type="button"
title="scroll_to_top"
data-scroll
>
<svg
xmlns="http://www.w3.org/2000/svg"
class="icon icon-tabler icon-tabler-arrow-up"
width="24"
height="24"
viewBox="0 0 24 24"
stroke-width=""
stroke="cuurentColor"
fill="none"
stroke-linecap="round"
stroke-linejoin="round"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<line x1="12" y1="5" x2="12" y2="19" />
<line x1="18" y1="11" x2="12" y2="5" />
<line x1="6" y1="11" x2="12" y2="5" />
</svg>
</button>
`;
}
initialize() {
this.initEventListeners();
}
initEventListeners() {
const offset = 200;
window.addEventListener("scroll", () => {
const scrollPos =
window.scrollY ||
window.scrollTop ||
document.getElementsByTagName("html")[0].scrollTop;
scrollPos > offset
? this.element.classList.add("is-active")
: this.element.classList.remove("is-active");
});
this.element.addEventListener("click", (event) => {
const isScroll = event.target.closest("[data-scroll]");
if (isScroll) {
window.scrollTo({ top: 0, behavior: 'smooth' });
}
});
}
render() {
const divElement = document.createElement("div");
divElement.innerHTML = this.template;
this.element = divElement.firstElementChild;
this.initialize();
}
remove() {
if (this.element) {
this.element.remove();
destroyEventListeners();
}
}
destroy() {
this.remove();
this.element = null;
}
}

@ -0,0 +1,29 @@
import BookSection from "./js/main/index.js";
import ButtonScroll from './js/scroll/index.js';
const input = document.getElementById("search");
const books = document.getElementById("books");
const content = document.getElementById("content");
const booksSection = new BookSection({
url: "../api/books/search",
label: "books",
});
const click = () => {
const query = document.getElementById("search").value;
if (query) {
booksSection.update({ query });
}
};
searchButton.addEventListener("click", click);
input.addEventListener("keypress", function (event) {
if (event.key === "Enter") {
click();
}
});
books.append(booksSection.element);
const scroll = new ButtonScroll()
content.append(scroll.element)

@ -0,0 +1,52 @@
const path = require('path');
const { createProxyMiddleware } = require('http-proxy-middleware');
const cors = require('cors');
const express = require('express');
const app = express();
const server = require('http').Server(app);
const router = require('express').Router()
const options = {
target: 'https://book.ogoun.name/', // target host
changeOrigin: true, // needed for virtual hosted sites
ws: true, // proxy websockets
logLevel: 'debug',
secure: false,
cookieDomainRewrite: {
'*': 'localhost',
},
onProxyRes(proxyRes, req, _res) {
if (proxyRes.headers['set-cookie'] !== undefined) {
req.cookie = proxyRes.headers['set-cookie'];
}
},
onProxyReq(proxyReq, req, _res) {
if (req && req.cookie !== undefined) {
proxyReq.setHeader('Cookie', req.cookie[0]);
}
},
};
const myLogger = function (req, res, next) {
next()
}
app.use(myLogger)
app.use(express.static(__dirname));
app.use(express.static(__dirname + '/js'));
app.use(express.static(__dirname + '/css'));
app.use(express.static(__dirname + '/constants'));
// app.get('/login', function (req, res) {
// res.sendFile(path.join(__dirname, '/login.html'));
// });
app.use('/', cors({
credentials: true,
origin: 'http://localhost:3000',
}), createProxyMiddleware(options));
server.listen(3001);

@ -0,0 +1,67 @@
using BukiVedi.Shared.Entities;
using BukiVedi.Shared.Models;
using BukiVedi.Shared.Services;
using BukiVedi.Shared.Services.Mappers;
using MongoDB.Driver;
namespace BukiVedi.Shared.Apps
{
public class AuthorHandler
: IAuthorHandler
{
private readonly ILibrary _library;
public AuthorHandler(ILibrary library)
{
if (library == null) throw new ArgumentNullException(nameof(library));
_library = library;
}
public async Task AddToFavorite(string id, OperationContext context)
{
if (context?.OperationInitiator?.Id == null) throw new InvalidOperationException("Unauthorized");
var exists_fiter = Builders<FavoriteAuthor>.Filter.And
(
Builders<FavoriteAuthor>.Filter.Eq(f => f.UserId, context.OperationInitiator.Id),
Builders<FavoriteAuthor>.Filter.Eq(f => f.AuthorId, id)
);
if (await Tables.FavoriteAuthors.Exists(exists_fiter) == false)
{
await Tables.FavoriteAuthors.Write(new FavoriteAuthor { AuthorId = id, UserId = context.OperationInitiator.Id });
}
}
public async Task<IEnumerable<AuthorInfo>> GetAllAuthors(OperationContext context)
{
var authors = (await Tables.Authors.GetAll()).Select(a => new AuthorInfo { Id = a.Id, Name = a.Name }).ToArray();
return authors;
}
public async Task<IEnumerable<AuthorInfo>> GetFavoriteAuthors(OperationContext context)
{
var authorIds = (await Tables.FavoriteAuthors.Get(Builders<FavoriteAuthor>.Filter.Eq(f => f.UserId, context.OperationInitiator.Id))).Select(f => f.AuthorId).ToHashSet();
var authors = (await Tables.Authors.Get(Builders<Author>.Filter.In(a => a.Id, authorIds))).Select(a => new AuthorInfo { Id = a.Id, Name = a.Name }).ToArray();
return authors;
}
public async Task RemoveFromFavorite(string id, OperationContext context)
{
if (context?.OperationInitiator?.Id == null) throw new InvalidOperationException("Unauthorized");
var exists_fiter = Builders<FavoriteAuthor>.Filter.And
(
Builders<FavoriteAuthor>.Filter.Eq(f => f.UserId, context.OperationInitiator.Id),
Builders<FavoriteAuthor>.Filter.Eq(f => f.AuthorId, id)
);
var records = await Tables.FavoriteAuthors.Get(exists_fiter);
foreach (var record in records)
{
await Tables.FavoriteAuthors.TryRemoveById(record.Id);
}
}
public async Task<IEnumerable<BookInfo>> SearchByAuthor(string id, OperationContext context)
{
var books = (await _library.SearchBooksByAuthor(id)).ToArray();
return await BookEntityMapper.Map(books);
}
}
}

@ -0,0 +1,243 @@
using Amazon.Runtime.Internal;
using BukiVedi.Shared.Entities;
using BukiVedi.Shared.Models;
using BukiVedi.Shared.Services;
using BukiVedi.Shared.Services.Mappers;
using MongoDB.Driver;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection.Metadata;
using System.Text;
using System.Threading.Tasks;
using ZeroLevel.Services.FileSystem;
namespace BukiVedi.Shared.Apps
{
public class BooksHandler
: IBooksHandler
{
private readonly ILibrary _library;
public BooksHandler(ILibrary library)
{
if (library == null) throw new ArgumentNullException(nameof(library));
_library = library;
}
public async Task AddAuthorsToFavorite(string id, OperationContext context)
{
var book = await Tables.Books.GetById(id);
if (book != null)
{
var account_id = context.OperationInitiator.Id;
var authors = book.AuthorIds;
if (!string.IsNullOrEmpty(account_id) && authors?.Count > 0)
{
foreach (var author in authors)
{
var exists_fiter = Builders<FavoriteAuthor>.Filter.And
(
Builders<FavoriteAuthor>.Filter.Eq(f => f.UserId, account_id),
Builders<FavoriteAuthor>.Filter.Eq(f => f.AuthorId, author)
);
if (await Tables.FavoriteAuthors.Exists(exists_fiter) == false)
{
await Tables.FavoriteAuthors.Write(new FavoriteAuthor { AuthorId = author, UserId = account_id });
}
}
}
}
}
public async Task AddBookToReadingQueue(string id, OperationContext context)
{
if (await Tables.Books.ExistById(id))
{
var account_id = context.OperationInitiator.Id;
if (!string.IsNullOrEmpty(account_id))
{
var exists_fiter = Builders<ReadQueueItem>.Filter.And
(
Builders<ReadQueueItem>.Filter.Eq(f => f.UserId, account_id),
Builders<ReadQueueItem>.Filter.Eq(f => f.BookId, id)
);
if (await Tables.ReadQueue.Exists(exists_fiter) == false)
{
await Tables.ReadQueue.Write(new ReadQueueItem { BookId = id, UserId = account_id, Timestamp = Timestamp.UtcNow });
}
}
}
}
public async Task AddToFavorite(string id, OperationContext context)
{
if (await Tables.Books.ExistById(id))
{
var account_id = context.OperationInitiator.Id;
if (!string.IsNullOrEmpty(account_id))
{
var exists_fiter = Builders<FavoriteBook>.Filter.And
(
Builders<FavoriteBook>.Filter.Eq(f => f.UserId, account_id),
Builders<FavoriteBook>.Filter.Eq(f => f.BookId, id)
);
if (await Tables.FavoriteBooks.Exists(exists_fiter) == false)
{
await Tables.FavoriteBooks.Write(new FavoriteBook { BookId = id, UserId = account_id });
}
}
}
}
public async Task BlockBook(string id, OperationContext context)
{
if (await Tables.Books.ExistById(id))
{
var account_id = context.OperationInitiator.Id;
if (!string.IsNullOrEmpty(account_id))
{
var exists_fiter = Builders<DisgustingBook>.Filter.And
(
Builders<DisgustingBook>.Filter.Eq(f => f.UserId, account_id),
Builders<DisgustingBook>.Filter.Eq(f => f.BookId, id)
);
if (await Tables.DisgustingBooks.Exists(exists_fiter) == false)
{
await Tables.DisgustingBooks.Write(new DisgustingBook { BookId = id, UserId = account_id });
}
}
}
}
public async Task BlockBookAuthor(string id, OperationContext context)
{
var book = await Tables.Books.GetById(id);
if (book != null)
{
var account_id = context.OperationInitiator.Id;
var authors = book.AuthorIds;
if (!string.IsNullOrEmpty(account_id) && authors?.Count > 0)
{
foreach (var author in authors)
{
var exists_fiter = Builders<DisgustingAuthor>.Filter.And
(
Builders<DisgustingAuthor>.Filter.Eq(f => f.UserId, account_id),
Builders<DisgustingAuthor>.Filter.Eq(f => f.AuthorId, author)
);
if (await Tables.DisgustingAuthors.Exists(exists_fiter) == false)
{
await Tables.DisgustingAuthors.Write(new DisgustingAuthor { AuthorId = author, UserId = account_id });
}
}
}
}
}
public async Task<(string, MemoryStream)> GetBlobData(string id, OperationContext context)
{
var content = new System.IO.MemoryStream();
var book = await _library.DownloadToStream(content, id);
string name = id;
if (book != null && string.IsNullOrWhiteSpace(book.Title) == false)
{
name = FSUtils.FileNameCorrection(book.Title);
}
content.Position = 0;
return (name, content);
}
public async Task RemoveFromFavorite(string id, OperationContext context)
{
if (context?.OperationInitiator?.Id == null) throw new InvalidOperationException("Unauthorized");
var exists_fiter = Builders<FavoriteBook>.Filter.And
(
Builders<FavoriteBook>.Filter.Eq(f => f.UserId, context.OperationInitiator.Id),
Builders<FavoriteBook>.Filter.Eq(f => f.BookId, id)
);
var records = await Tables.FavoriteBooks.Get(exists_fiter);
foreach (var record in records)
{
await Tables.FavoriteBooks.TryRemoveById(record.Id);
}
}
public async Task RemoveFromReadingQueue(string id, OperationContext context)
{
if (context?.OperationInitiator?.Id == null) throw new InvalidOperationException("Unauthorized");
var exists_fiter = Builders<ReadQueueItem>.Filter.And
(
Builders<ReadQueueItem>.Filter.Eq(f => f.UserId, context.OperationInitiator.Id),
Builders<ReadQueueItem>.Filter.Eq(f => f.BookId, id)
);
var records = await Tables.ReadQueue.Get(exists_fiter);
foreach (var record in records)
{
await Tables.ReadQueue.TryRemoveById(record.Id);
}
}
public async Task<IEnumerable<BookInfo>> Search(string query, string? tag, OperationContext context)
{
if (string.IsNullOrWhiteSpace(query) == false)
{
switch (query.Trim().ToLowerInvariant())
{
case "@favorites":
{
var books = (await _library.SearchFavoritesBooks(context.OperationInitiator.Id)).ToArray();
return await BookEntityMapper.Map(books);
}
case "@favoriteauthors":
{
var books = (await _library.SearchFavoriteAuthorsBooks(context.OperationInitiator.Id)).ToArray();
return await BookEntityMapper.Map(books);
}
case "@tagged":
{
var books = (await _library.SearchTaggedBooks(context.OperationInitiator.Id, tag: tag!)).ToArray();
return await BookEntityMapper.Map(books);
}
case "@blocked":
{
var books = (await _library.SearchBlockedBooks(context.OperationInitiator.Id)).ToArray();
return await BookEntityMapper.Map(books);
}
case "@toread":
{
var books = (await _library.SearchToReadBooks(context.OperationInitiator.Id)).ToArray();
return await BookEntityMapper.Map(books);
}
default:
{
var books = (await _library.SearchBooks(query)).ToArray();
return await BookEntityMapper.Map(books);
}
}
}
return Enumerable.Empty<BookInfo>();
}
public async Task UnblockBook(string id, OperationContext context)
{
if (context?.OperationInitiator?.Id == null) throw new InvalidOperationException("Unauthorized");
var account_id = context.OperationInitiator.Id;
if (!string.IsNullOrEmpty(account_id))
{
var exists_fiter = Builders<DisgustingBook>.Filter.And
(
Builders<DisgustingBook>.Filter.Eq(f => f.UserId, account_id),
Builders<DisgustingBook>.Filter.Eq(f => f.BookId, id)
);
var records = await Tables.DisgustingBooks.Get(exists_fiter);
foreach (var record in records)
{
await Tables.DisgustingBooks.TryRemoveById(record.Id);
}
}
}
}
}

@ -0,0 +1,13 @@
using BukiVedi.Shared.Models;
namespace BukiVedi.Shared.Apps
{
public interface IAuthorHandler
{
Task<IEnumerable<BookInfo>> SearchByAuthor(string id, OperationContext context);
Task AddToFavorite(string id, OperationContext context);
Task RemoveFromFavorite(string id, OperationContext context);
Task<IEnumerable<AuthorInfo>> GetAllAuthors(OperationContext context);
Task<IEnumerable<AuthorInfo>> GetFavoriteAuthors(OperationContext context);
}
}

@ -0,0 +1,18 @@
using BukiVedi.Shared.Models;
namespace BukiVedi.Shared.Apps
{
public interface IBooksHandler
{
Task<IEnumerable<BookInfo>> Search(string query, string? tag, OperationContext context);
Task AddToFavorite(string id, OperationContext context);
Task AddAuthorsToFavorite(string id, OperationContext context);
Task BlockBook(string id, OperationContext context);
Task BlockBookAuthor(string id, OperationContext context);
Task AddBookToReadingQueue(string id, OperationContext context);
Task<(string, MemoryStream)> GetBlobData(string id, OperationContext context);
Task UnblockBook(string id, OperationContext context);
Task RemoveFromFavorite(string id, OperationContext context);
Task RemoveFromReadingQueue(string id, OperationContext context);
}
}

@ -0,0 +1,12 @@
using BukiVedi.Shared.Models;
namespace BukiVedi.Shared.Apps
{
public interface ITagsHandler
{
Task AppendTag(string bookId, string name, OperationContext context);
Task<bool> RemoveTag(string id, OperationContext context);
Task<IEnumerable<string>> GetUserTags(OperationContext context);
Task<IEnumerable<BookInfo>> Search(string id, OperationContext context);
}
}

@ -0,0 +1,56 @@
using BukiVedi.Shared.Entities;
using BukiVedi.Shared.Models;
using BukiVedi.Shared.Services;
using BukiVedi.Shared.Services.Mappers;
using MongoDB.Driver;
namespace BukiVedi.Shared.Apps
{
public class TagsHandler
: ITagsHandler
{
private readonly ILibrary _library;
public TagsHandler(ILibrary library)
{
if (library == null) throw new ArgumentNullException(nameof(library));
_library = library;
}
public async Task AppendTag(string bookId, string name, OperationContext context)
{
if (string.IsNullOrWhiteSpace(name) == false && await Tables.Books.ExistById(bookId))
{
name = name.Trim().ToLowerInvariant();
var tagFilter = Builders<UserTag>.Filter.And(Builders<UserTag>.Filter.Eq(t => t.BookId, bookId), Builders<UserTag>.Filter.Eq(t => t.Name, name));
if (false == await Tables.UserTag.Exists(tagFilter))
{
await Tables.UserTag.Write(new UserTag { BookId = bookId, Name = name, UserId = context.OperationInitiator.Id });
}
}
}
public async Task<IEnumerable<string>> GetUserTags(OperationContext context)
{
return (await Tables.UserTag.Get(Builders<UserTag>.Filter.Eq(t => t.UserId, context.OperationInitiator.Id)))?.Select(t => t.Name)!;
}
public async Task<bool> RemoveTag(string id, OperationContext context)
{
if (string.IsNullOrWhiteSpace(id) == false && await Tables.UserTag.ExistById(id))
{
return await Tables.UserTag.TryRemoveById(id);
}
return false;
}
public async Task<IEnumerable<BookInfo>> Search(string id, OperationContext context)
{
if (string.IsNullOrWhiteSpace(id) == false)
{
var books = await _library.SearchByTagBooks(context.OperationInitiator.Id, id);
return await BookEntityMapper.Map(books);
}
return Enumerable.Empty<BookInfo>();
}
}
}

@ -0,0 +1,10 @@
namespace BukiVedi.Shared.Models
{
public class AuthorInfo
{
public string Id { get; set; }
public string Name { get; set; }
public bool IsFavorite { get; set; }
public bool IsBlocked { get; set; }
}
}

@ -9,10 +9,10 @@ namespace BukiVedi.Shared.Models
[SleoIndex("title", 100.0f, true)]
public string Title { get; set; }
[SleoIndex("titlelm", 100.0f)]
[SleoIndex("titlelm", 90.0f)]
public string TitleLemmas { get; set; }
[SleoIndex("author", 100.0f, true)]
[SleoIndex("author", 90.0f, true)]
public string Author { get; set; }
[SleoIndex("genre", 10.0f, true)]

@ -0,0 +1,15 @@
namespace BukiVedi.Shared.Models
{
public class BookDto
{
public int Year { get; set; }
public string Title { get; set; }
public string[] TitleLemmas { get; set; }
public string Description { get; set; }
public string[] Authors { get; set; }
public string[] Genres { get; set; }
public string ArchivePath { get; set; }
public int ArchiveIndex { get; set; }
public BookFormat Format { get; set; }
}
}

@ -2,14 +2,61 @@
{
public class BookInfo
{
public int Year { get; set; }
/// <summary>
/// Идентификатор
/// </summary>
public string Id { get; set; }
/// <summary>
/// Изображение(урл)
/// </summary>
public string ImageUrl { get; set; }
/// <summary>
/// Название
/// </summary>
public string Title { get; set; }
public string[] TitleLemmas { get; set; }
/// <summary>
/// Описание
/// </summary>
public string Description { get; set; }
public string[] Authors { get; set; }
public string[] Genres { get; set; }
public string ArchivePath { get; set; }
public int ArchiveIndex { get; set; }
public BookFormat Format { get; set; }
/// <summary>
/// Заметка
/// </summary>
public string Note { get; set; }
/// <summary>
/// Авторы(массив объектов с полями id; имя автора)
/// </summary>
public AuthorInfo[] Authors { get; set; }
/// <summary>
/// Жанры(массив объектов с полями id; название жанра)
/// </summary>
public GenreInfo[] Genres { get; set; }
/// <summary>
/// Серия
/// </summary>
public string Series { get; set; }
/// <summary>
/// Подсерия
/// </summary>
public string Subseries { get; set; }
/// <summary>
/// Теги(массив объектов с полями id; имя тега)
/// </summary>
public IEnumerable<TagInfo> Tags { get; set; }
/// <summary>
/// Год издания
/// </summary>
public int Year { get; set; }
/// <summary>
/// Формат книги
/// </summary>
public string Format { get; set; }
/// <summary>
/// Книга заблокирована пользователем
/// </summary>
public bool IsBlocked { get; set; }
/// <summary>
/// Книга находится в избранном
/// </summary>
public bool IsFavorite { get; set; }
}
}

@ -0,0 +1,8 @@
namespace BukiVedi.Shared.Models
{
public class FormatInfo
{
public string Id { get; set; }
public string Name { get; set; }
}
}

@ -0,0 +1,8 @@
namespace BukiVedi.Shared.Models
{
public class GenreInfo
{
public string Id { get; set; }
public string Name { get; set; }
}
}

@ -0,0 +1,8 @@
namespace BukiVedi.Shared.Models
{
public class TagInfo
{
public string Id { get; set; }
public string Name { get; set; }
}
}

@ -19,7 +19,7 @@ namespace BukiVedi.Shared.Services
Task<IEnumerable<BookEntity>> SearchBlockedBooks(string accountId);
Task<IEnumerable<BookEntity>> SearchFavoriteAuthorsBooks(string accountId);
Task<IEnumerable<BookEntity>> SearchToReadBooks(string accountId);
Task DownloadToStream(Stream stream, string id);
Task<Book> DownloadToStream(Stream stream, string id);
}
public class Library
@ -213,13 +213,15 @@ namespace BukiVedi.Shared.Services
}
}
public async Task DownloadToStream(Stream stream, string id)
public async Task<Book> DownloadToStream(Stream stream, string id)
{
var b = await Tables.Books.GetById(id);
if (b != null)
{
await _library.Download(Path.Combine(_libraryPath, b.ArchivePath), b.ArchiveIndex, stream);
return b;
}
return null;
}
public async Task<IEnumerable<BookEntity>> SearchBooks(string query)

@ -0,0 +1,41 @@
using BukiVedi.Shared.Entities;
using BukiVedi.Shared.Models;
using MongoDB.Driver;
namespace BukiVedi.Shared.Services.Mappers
{
public class BookEntityMapper
{
public static async Task<IEnumerable<BookInfo>> Map(IEnumerable<BookEntity> books)
{
var booksIds = books.Select(x => x.Id).ToList();
var tags_list = (await Tables.UserTag.Get(Builders<UserTag>.Filter.In(t => t.BookId, booksIds)));
var tags = new Dictionary<string, List<TagInfo>>();
foreach (var t in tags_list)
{
if (tags.TryGetValue(t.BookId, out var list)) { list.Add(new TagInfo { Id = t.Id, Name = t.Name }); }
else
{
tags.Add(t.BookId,
new List<TagInfo>
{
new TagInfo { Id = t.Id, Name = t.Name }
});
}
}
return books.Select(book =>
new BookInfo
{
Authors = book.Authors.Select(a => new AuthorInfo { Id = a.Id, Name = a.Name }).ToArray(),
Description = book.Description,
Format = book.Format,
Id = book.Id,
Genres = new GenreInfo[1] { new GenreInfo { Id = book.Genre.Id, Name = book.Genre.Code } },
Title = book.Title,
Year = book.Year,
Tags = tags.ContainsKey(book.Id) ? tags[book.Id] : null!
});
}
}
}

@ -19,12 +19,12 @@ namespace BukiVedi.Shared.Services
_zipFilesPath = zipFilesPath;
}
public BookInfo ReadBookInfo(string archivePath, int index)
public BookDto ReadBookInfo(string archivePath, int index)
{
using (var zip = ZipFile.OpenRead(archivePath))
{
var entry = zip.Entries[index];
BookInfo book = null;
BookDto book = null;
if (entry.Name.EndsWith(".fb2", StringComparison.OrdinalIgnoreCase))
{
using (var s = entry.Open())
@ -36,7 +36,7 @@ namespace BukiVedi.Shared.Services
return null!;
}
public IEnumerable<BookInfo> ReadBooks()
public IEnumerable<BookDto> ReadBooks()
{
foreach (var zipFile in Directory.EnumerateFiles(_zipFilesPath, "*.zip"))
{
@ -45,7 +45,7 @@ namespace BukiVedi.Shared.Services
var index = 0;
foreach (var e in zip.Entries)
{
BookInfo book = null;
BookDto book = null;
if (e.Name.EndsWith(".fb2", StringComparison.OrdinalIgnoreCase))
{
using (var s = e.Open())
@ -113,7 +113,7 @@ namespace BukiVedi.Shared.Services
#region FB2
private static XmlLoadSettings _fbSettings = new XmlLoadSettings(new XmlReaderSettings { DtdProcessing = DtdProcessing.Ignore });
private static BookInfo ReadFromFb2(Stream s, string name, string path, int index)
private static BookDto ReadFromFb2(Stream s, string name, string path, int index)
{
try
{
@ -124,7 +124,7 @@ namespace BukiVedi.Shared.Services
var authors = Authors(file.TitleInfo.BookAuthors);
var title = file.TitleInfo.BookTitle?.Text;
var genres = file.TitleInfo?.Genres?.Select(g => g.Genre)?.ToArray();
return new BookInfo
return new BookDto
{
ArchiveIndex = index,
ArchivePath = path,

@ -14,7 +14,7 @@
"LemmaSharpPrebuiltFull": "1.0.0",
"MongoDB.Driver": "2.24.0",
"Sleopok.Engine": "1.0.0",
"ZeroLevel": "1.0.0"
"ZeroLevel": "4.0.0"
},
"runtime": {
"BukiVedi.Shared.dll": {}
@ -201,13 +201,13 @@
},
"Sleopok.Engine/1.0.0": {
"dependencies": {
"ZeroLevel": "1.0.0"
"ZeroLevel": "4.0.0"
},
"runtime": {
"Sleopok.Engine.dll": {}
}
},
"ZeroLevel/1.0.0": {
"ZeroLevel/4.0.0": {
"runtime": {
"ZeroLevel.dll": {}
}
@ -381,7 +381,7 @@
"serviceable": false,
"sha512": ""
},
"ZeroLevel/1.0.0": {
"ZeroLevel/4.0.0": {
"type": "project",
"serviceable": false,
"sha512": ""

@ -14,7 +14,7 @@
"LemmaSharpPrebuiltFull": "1.0.0",
"MongoDB.Driver": "2.24.0",
"Sleopok.Engine": "1.0.0",
"ZeroLevel": "1.0.0"
"ZeroLevel": "4.0.0"
},
"runtime": {
"BukiVedi.Shared.dll": {}
@ -201,13 +201,13 @@
},
"Sleopok.Engine/1.0.0": {
"dependencies": {
"ZeroLevel": "1.0.0"
"ZeroLevel": "4.0.0"
},
"runtime": {
"Sleopok.Engine.dll": {}
}
},
"ZeroLevel/1.0.0": {
"ZeroLevel/4.0.0": {
"runtime": {
"ZeroLevel.dll": {}
}
@ -381,7 +381,7 @@
"serviceable": false,
"sha512": ""
},
"ZeroLevel/1.0.0": {
"ZeroLevel/4.0.0": {
"type": "project",
"serviceable": false,
"sha512": ""

@ -5,7 +5,7 @@
},
"projects": {
"F:\\Documents\\GitHub\\Zero\\ZeroLevel\\ZeroLevel.csproj": {
"version": "1.0.0",
"version": "4.0.0",
"restore": {
"projectUniqueName": "F:\\Documents\\GitHub\\Zero\\ZeroLevel\\ZeroLevel.csproj",
"projectName": "ZeroLevel",

@ -14,7 +14,7 @@ using System.Reflection;
[assembly: System.Reflection.AssemblyCompanyAttribute("BukiVedi.Shared")]
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+653045cfe4c19cb8cabc63ce1b8f61d4b7e4f26e")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+431f2503a837ccf39eac97076a865db39f86a8dd")]
[assembly: System.Reflection.AssemblyProductAttribute("BukiVedi.Shared")]
[assembly: System.Reflection.AssemblyTitleAttribute("BukiVedi.Shared")]
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]

@ -1 +1 @@
6662423c1e23f623328b320f21205ebeff7a4aebfe8c7b0b24e3f18247b7d14a
22258ed3f3bd48ae74b9c3607cf0cf82ec9b3322b631691b32743438f798c7cc

@ -1 +1 @@
2bddd0bc3dcd27073c70a4760f8dbf79dac12620146c67283751aa5c04e62c2b
8f1511391c660118f311ede1de029df8d3c4dca0dcff3c3fe53339a3d1836ea1

@ -14,7 +14,7 @@ using System.Reflection;
[assembly: System.Reflection.AssemblyCompanyAttribute("BukiVedi.Shared")]
[assembly: System.Reflection.AssemblyConfigurationAttribute("Release")]
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+653045cfe4c19cb8cabc63ce1b8f61d4b7e4f26e")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+431f2503a837ccf39eac97076a865db39f86a8dd")]
[assembly: System.Reflection.AssemblyProductAttribute("BukiVedi.Shared")]
[assembly: System.Reflection.AssemblyTitleAttribute("BukiVedi.Shared")]
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]

@ -1 +1 @@
28e06cd4b9a59e2ff22da92879fdac725f071bab5552441829896eec6bfa3411
06715856c937a6aa0ade3b1fa065928029591cc434dd76545f239523dd28567b

@ -1 +1 @@
79899f010b0c66fc84b9abdf331440593c067d267d0f470e1f4033e933b4c19e
946ae02ae1d24f78debab34bdbac2f87234e55c2d9142e2f73b46c18adb4ce88

@ -340,7 +340,7 @@
"type": "project",
"framework": ".NETCoreApp,Version=v8.0",
"dependencies": {
"ZeroLevel": "1.0.0"
"ZeroLevel": "4.0.0"
},
"compile": {
"bin/placeholder/Sleopok.Engine.dll": {}
@ -349,7 +349,7 @@
"bin/placeholder/Sleopok.Engine.dll": {}
}
},
"ZeroLevel/1.0.0": {
"ZeroLevel/4.0.0": {
"type": "project",
"framework": ".NETStandard,Version=v2.1",
"compile": {
@ -666,7 +666,7 @@
"type": "project",
"framework": ".NETCoreApp,Version=v8.0",
"dependencies": {
"ZeroLevel": "1.0.0"
"ZeroLevel": "4.0.0"
},
"compile": {
"bin/placeholder/Sleopok.Engine.dll": {}
@ -675,7 +675,7 @@
"bin/placeholder/Sleopok.Engine.dll": {}
}
},
"ZeroLevel/1.0.0": {
"ZeroLevel/4.0.0": {
"type": "project",
"framework": ".NETStandard,Version=v2.1",
"compile": {
@ -1203,7 +1203,7 @@
"path": "../../../sleopok/src/Sleopok/Sleopok.Engine/Sleopok.Engine.csproj",
"msbuildProject": "../../../sleopok/src/Sleopok/Sleopok.Engine/Sleopok.Engine.csproj"
},
"ZeroLevel/1.0.0": {
"ZeroLevel/4.0.0": {
"type": "project",
"path": "F:\\Documents\\GitHub\\Zero\\ZeroLevel\\ZeroLevel.csproj",
"msbuildProject": "F:\\Documents\\GitHub\\Zero\\ZeroLevel\\ZeroLevel.csproj"
@ -1217,7 +1217,7 @@
"LemmaSharpPrebuiltFull >= 1.0.0",
"MongoDB.Driver >= 2.24.0",
"Sleopok.Engine >= 1.0.0",
"ZeroLevel >= 1.0.0"
"ZeroLevel >= 4.0.0"
]
},
"packageFolders": {

@ -1,6 +1,6 @@
{
"version": 2,
"dgSpecHash": "yT5XSXnkL8QDzBzWmb4d84rvHwETnt31t/sfuePGLwfvd9Qc6aS9gJSYjBmenihhmuQWC/N0ANii96e18tjqlQ==",
"dgSpecHash": "I5NF3rZJZUmDLwIKUi7T7NRpUaNrPoHKlXnBGtdzl5MdYPzg4P1cn162b2nsZJbsHNBvnds14OIqZJxmohNxNw==",
"success": true,
"projectFilePath": "G:\\Documents\\GitHub\\BukiVedi\\src\\BukiVedi.Shared\\BukiVedi.Shared.csproj",
"expectedPackageFiles": [
@ -22,7 +22,8 @@
"C:\\Users\\Ogoun\\.nuget\\packages\\system.runtime.compilerservices.unsafe\\5.0.0\\system.runtime.compilerservices.unsafe.5.0.0.nupkg.sha512",
"C:\\Users\\Ogoun\\.nuget\\packages\\system.security.accesscontrol\\5.0.0\\system.security.accesscontrol.5.0.0.nupkg.sha512",
"C:\\Users\\Ogoun\\.nuget\\packages\\system.security.principal.windows\\5.0.0\\system.security.principal.windows.5.0.0.nupkg.sha512",
"C:\\Users\\Ogoun\\.nuget\\packages\\zstdsharp.port\\0.7.3\\zstdsharp.port.0.7.3.nupkg.sha512"
"C:\\Users\\Ogoun\\.nuget\\packages\\zstdsharp.port\\0.7.3\\zstdsharp.port.0.7.3.nupkg.sha512",
"C:\\Users\\Ogoun\\.nuget\\packages\\zerolevel\\4.0.0\\zerolevel.4.0.0.nupkg.sha512"
],
"logs": []
}

@ -9,6 +9,13 @@
<ItemGroup>
<ProjectReference Include="..\..\..\sleopok\src\Sleopok\Sleopok.Engine\Sleopok.Engine.csproj" />
<ProjectReference Include="..\BukiVedi.Shared\BukiVedi.Shared.csproj" />
</ItemGroup>
<ItemGroup>
<None Update="config.ini">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>

@ -1,4 +1,6 @@
using Sleopok.Engine.Services.Storage;
using BukiVedi.Shared.Services;
using Sleopok.Engine.Services;
using Sleopok.Engine.Services.Storage;
namespace IndexExportTest
{
@ -6,16 +8,22 @@ namespace IndexExportTest
{
static async Task Main(string[] args)
{
var store = new DataStorage(@"/var/www/books");
var library = new Library();
var store = new DataStorage(@"H:\TEST");
await Dump(store, "author");
await Dump(store, "genre");
await Dump(store, "title");
await Dump(store, "titlelm");
Console.ReadLine();
}
static async Task Dump(DataStorage store, string field)
{
using (var fs = new FileStream($"/var/www/{field}.txt", FileMode.Create, FileAccess.Write, FileShare.None))
using (var fs = new FileStream($"H:/TEST1/{field}.txt", FileMode.Create, FileAccess.Write, FileShare.None))
{
await store.Dump(field, fs);
}

@ -0,0 +1,9 @@
login=ogoun
password=A3n1g4e1l5#
libraryPath=I:\Library\Flibusta.Net
[MongoDB]
ConnectionString="mongodb://192.168.0.222:27017"
[Sleopok]
path=H:\TEST

@ -179,7 +179,7 @@
"LemmaSharpPrebuiltFull": "1.0.0",
"MongoDB.Driver": "2.24.0",
"Sleopok.Engine": "1.0.0",
"ZeroLevel": "1.0.0"
"ZeroLevel": "4.0.0"
},
"runtime": {
"BukiVedi.Shared.dll": {}
@ -209,13 +209,13 @@
},
"Sleopok.Engine/1.0.0": {
"dependencies": {
"ZeroLevel": "1.0.0"
"ZeroLevel": "4.0.0"
},
"runtime": {
"Sleopok.Engine.dll": {}
}
},
"ZeroLevel/1.0.0": {
"ZeroLevel/4.0.0": {
"runtime": {
"ZeroLevel.dll": {}
}
@ -394,7 +394,7 @@
"serviceable": false,
"sha512": ""
},
"ZeroLevel/1.0.0": {
"ZeroLevel/4.0.0": {
"type": "project",
"serviceable": false,
"sha512": ""

@ -14,7 +14,7 @@ using System.Reflection;
[assembly: System.Reflection.AssemblyCompanyAttribute("TitleReader")]
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+653045cfe4c19cb8cabc63ce1b8f61d4b7e4f26e")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+431f2503a837ccf39eac97076a865db39f86a8dd")]
[assembly: System.Reflection.AssemblyProductAttribute("TitleReader")]
[assembly: System.Reflection.AssemblyTitleAttribute("TitleReader")]
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]

@ -1 +1 @@
b6e867e96464d226d6f64f5bb8ff88fd91a7dc10b0cbc8df658695411d89c7c7
d7606117e667c055ed565f5f0d94c916cbdbb0bbb171442e9a9d4b51ab356451

@ -14,7 +14,7 @@ using System.Reflection;
[assembly: System.Reflection.AssemblyCompanyAttribute("TitleReader")]
[assembly: System.Reflection.AssemblyConfigurationAttribute("Release")]
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+653045cfe4c19cb8cabc63ce1b8f61d4b7e4f26e")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+431f2503a837ccf39eac97076a865db39f86a8dd")]
[assembly: System.Reflection.AssemblyProductAttribute("TitleReader")]
[assembly: System.Reflection.AssemblyTitleAttribute("TitleReader")]
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]

@ -1 +1 @@
588b6177dc8dadc34104d72c7f17ba8cc3301324d19dcc1fef526a0a4fcaa5de
a7282ddb1bbc4aea6cf73d9f5cd24625e715891dd94841b8c41be90b8822b144

@ -5,7 +5,7 @@
},
"projects": {
"F:\\Documents\\GitHub\\Zero\\ZeroLevel\\ZeroLevel.csproj": {
"version": "1.0.0",
"version": "4.0.0",
"restore": {
"projectUniqueName": "F:\\Documents\\GitHub\\Zero\\ZeroLevel\\ZeroLevel.csproj",
"projectName": "ZeroLevel",

@ -312,7 +312,7 @@
"LemmaSharpPrebuiltFull": "1.0.0",
"MongoDB.Driver": "2.24.0",
"Sleopok.Engine": "1.0.0",
"ZeroLevel": "1.0.0"
"ZeroLevel": "4.0.0"
},
"compile": {
"bin/placeholder/BukiVedi.Shared.dll": {}
@ -359,7 +359,7 @@
"type": "project",
"framework": ".NETCoreApp,Version=v8.0",
"dependencies": {
"ZeroLevel": "1.0.0"
"ZeroLevel": "4.0.0"
},
"compile": {
"bin/placeholder/Sleopok.Engine.dll": {}
@ -368,7 +368,7 @@
"bin/placeholder/Sleopok.Engine.dll": {}
}
},
"ZeroLevel/1.0.0": {
"ZeroLevel/4.0.0": {
"type": "project",
"framework": ".NETStandard,Version=v2.1",
"compile": {
@ -901,7 +901,7 @@
"path": "../../../sleopok/src/Sleopok/Sleopok.Engine/Sleopok.Engine.csproj",
"msbuildProject": "../../../sleopok/src/Sleopok/Sleopok.Engine/Sleopok.Engine.csproj"
},
"ZeroLevel/1.0.0": {
"ZeroLevel/4.0.0": {
"type": "project",
"path": "F:\\Documents\\GitHub\\Zero\\ZeroLevel\\ZeroLevel.csproj",
"msbuildProject": "F:\\Documents\\GitHub\\Zero\\ZeroLevel\\ZeroLevel.csproj"

@ -1,6 +1,6 @@
{
"version": 2,
"dgSpecHash": "kWMsTMYfHKFRfmEETdspspZMDX5Q7j8a9bwhSWnX9GUwk9jMvNjEEVpRTQ1BcySO4xIeyDgBFMoFZ/6NKYNuOg==",
"dgSpecHash": "Sw/P8SWtQDkQsfDVJxqQlQjTkIGfP1lboPxZ+pAQBR6QlHJi296GVIfCq+cIhVP0NOhSpqFErs2oyZY9AwwjkA==",
"success": true,
"projectFilePath": "G:\\Documents\\GitHub\\BukiVedi\\src\\TitleReader\\TitleReader.csproj",
"expectedPackageFiles": [
@ -22,7 +22,8 @@
"C:\\Users\\Ogoun\\.nuget\\packages\\system.runtime.compilerservices.unsafe\\5.0.0\\system.runtime.compilerservices.unsafe.5.0.0.nupkg.sha512",
"C:\\Users\\Ogoun\\.nuget\\packages\\system.security.accesscontrol\\5.0.0\\system.security.accesscontrol.5.0.0.nupkg.sha512",
"C:\\Users\\Ogoun\\.nuget\\packages\\system.security.principal.windows\\5.0.0\\system.security.principal.windows.5.0.0.nupkg.sha512",
"C:\\Users\\Ogoun\\.nuget\\packages\\zstdsharp.port\\0.7.3\\zstdsharp.port.0.7.3.nupkg.sha512"
"C:\\Users\\Ogoun\\.nuget\\packages\\zstdsharp.port\\0.7.3\\zstdsharp.port.0.7.3.nupkg.sha512",
"C:\\Users\\Ogoun\\.nuget\\packages\\zerolevel\\4.0.0\\zerolevel.4.0.0.nupkg.sha512"
],
"logs": []
}
Loading…
Cancel
Save

Powered by TurnKey Linux.