SearchQuery commands

@favorites
main
Ogoun 7 months ago
parent a3d0f6854d
commit 1a3354bfe4

@ -19,6 +19,11 @@ namespace BukiVedi.App.Controllers
} }
/// <summary>
/// Аутентификация на сайте через логин пароль
/// </summary>
/// <param name="request">Логин/пароль</param>
/// <returns></returns>
[HttpPost("/api/auth")] [HttpPost("/api/auth")]
[ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status400BadRequest)]

@ -0,0 +1,59 @@
using BukiVedi.App.Responces;
using BukiVedi.App.Services.Mappers;
using BukiVedi.Shared.Entities;
using BukiVedi.Shared.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using MongoDB.Driver;
namespace BukiVedi.App.Controllers
{
[Route("api/author")]
[ApiController]
[Authorize("authorized")]
public class AuthorsController
: BaseController
{
private readonly ILibrary _library;
public AuthorsController(ILibrary library)
: base()
{
_library = library;
}
/// <summary>
/// Поиск книг указанного автора
/// </summary>
/// <param name="id">Идентификатор автора</param>
/// <returns>Список книг</returns>
[HttpPost("{id}/books")]
public async Task<ActionResult<IEnumerable<BookResponse>>> SearchByAuthor([FromRoute] string id)
{
var books = (await _library.SearchBooksByAuthor(id)).ToArray();
return Ok(books.Select(b => BookEntityMapper.Map(b)));
}
/// <summary>
/// Получить список всех авторов
/// </summary>
/// <returns>Список авторов</returns>
[HttpGet()]
public async Task<ActionResult<IEnumerable<AuthorInfo>>> GetAllAuthors()
{
var authors = (await Tables.Authors.GetAll()).Select(a => new AuthorInfo { Id = a.Id, Name = a.Name }).ToArray();
return Ok(authors);
}
/// <summary>
/// Получить список авторов, которых пользователь добавил в избранное
/// </summary>
/// <returns>Список авторов</returns>
[HttpGet("favorite")]
public async Task<ActionResult<IEnumerable<AuthorInfo>>> GetFavoriteAuthors()
{
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);
}
}
}

@ -11,6 +11,7 @@ namespace BukiVedi.App.Controllers
{ {
[Authorize("authorized")] [Authorize("authorized")]
[ApiController] [ApiController]
[Route("api/books")]
public class BooksController public class BooksController
: BaseController : BaseController
{ {
@ -21,24 +22,85 @@ namespace BukiVedi.App.Controllers
_library = library; _library = library;
} }
[HttpPost("/api/books/search")] #region SEARCH
/// <summary>
/// Поиск книг по запросу
/// </summary>
/// <param name="request">Поисковый запрос</param>
/// <returns>Список найденных книг</returns>
[HttpPost("search")]
public async Task<ActionResult<IEnumerable<BookResponse>>> Search([FromBody] QueryRequest request) public async Task<ActionResult<IEnumerable<BookResponse>>> Search([FromBody] QueryRequest request)
{ {
var books = (await _library.SearchBooks(request.Query)).ToArray(); if (string.IsNullOrWhiteSpace(request.Query) == false)
return Ok(books.Select(b => BookEntityMapper.Map(b))); {
} switch (request.Query.Trim().ToLowerInvariant())
{
case "@favorites":
{
var books = (await _library.SearchFavoritesBooks(OperationContext.OperationInitiator.Id)).ToArray();
return Ok(books.Select(b =>
{
var bu = BookEntityMapper.Map(b);
bu.IsFavorite = true; // TODO сделать проверкой по справочнику в кеше
return bu;
}));
}
case "@favoriteauthors":
{
var books = (await _library.SearchFavoriteAuthorsBooks(OperationContext.OperationInitiator.Id)).ToArray();
return Ok(books.Select(b =>
{
var bu = BookEntityMapper.Map(b);
bu.IsFavorite = true; // TODO сделать проверкой по справочнику в кеше
return bu;
}));
}
case "@tagged":
{
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(books.Select(b => BookEntityMapper.Map(b)));
}
case "@blocked":
{
var books = (await _library.SearchBlockedBooks(OperationContext.OperationInitiator.Id)).ToArray();
return Ok(books.Select(b =>
{
var bu = BookEntityMapper.Map(b);
bu.IsBlocked = true; // TODO сделать проверкой по справочнику в кеше
return bu;
}));
}
case "@toread":
{
var books = (await _library.SearchToReadBooks(OperationContext.OperationInitiator.Id)).ToArray();
return Ok(books.Select(b => BookEntityMapper.Map(b)));
}
[HttpPost("/api/books/search/author/{id}")] default:
public async Task<ActionResult<IEnumerable<BookResponse>>> SearchByAuthor([FromRoute] string id) {
{ var books = (await _library.SearchBooks(request.Query)).ToArray();
var books = (await _library.SearchBooksByAuthor(id)).ToArray(); return Ok(books.Select(b => BookEntityMapper.Map(b)));
return Ok(books.Select(b => BookEntityMapper.Map(b))); }
}
}
return Ok(Enumerable.Empty<BookResponse>());
} }
#endregion
[HttpPost("/api/books/{id}/favorite")] /// <summary>
public async Task<ActionResult<IEnumerable<BookResponse>>> AddToFavorite([FromRoute] string id) /// Добавление книги в избранное
/// </summary>
/// <param name="id">Идентификатор книги</param>
/// <returns>Ok</returns>
[HttpPost("{id}/favorite")]
public async Task<IActionResult> AddToFavorite([FromRoute] string id)
{ {
if (await Tables.Books.ExistById(id)) if (await Tables.Books.ExistById(id))
{ {
@ -59,8 +121,45 @@ namespace BukiVedi.App.Controllers
return Ok(); return Ok();
} }
[HttpPost("/api/books/{id}/block")] /// <summary>
public async Task<ActionResult<IEnumerable<BookResponse>>> BlockBook([FromRoute] string id) /// Добавление авторов книги в избранное
/// </summary>
/// <param name="id">Идентификатор книги</param>
/// <returns>Ok</returns>
[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 });
}
}
}
}
return Ok();
}
/// <summary>
/// Добавление книги в игнор
/// </summary>
/// <param name="id">Идентификатор книги</param>
/// <returns>Ok</returns>
[HttpPost("{id}/block")]
public async Task<IActionResult> BlockBook([FromRoute] string id)
{ {
if (await Tables.Books.ExistById(id)) if (await Tables.Books.ExistById(id))
{ {
@ -81,7 +180,12 @@ namespace BukiVedi.App.Controllers
return Ok(); return Ok();
} }
[HttpPost("/api/books/{id}/author/block")] /// <summary>
/// Добавление авторов книги в игнор
/// </summary>
/// <param name="id">Идентификатор книги, чьих авторов нужно заблокировать</param>
/// <returns>Ok</returns>
[HttpPost("{id}/author/block")]
public async Task<ActionResult<IEnumerable<BookResponse>>> BlockBookAuthor([FromRoute] string id) public async Task<ActionResult<IEnumerable<BookResponse>>> BlockBookAuthor([FromRoute] string id)
{ {
var book = await Tables.Books.GetById(id); var book = await Tables.Books.GetById(id);
@ -108,8 +212,13 @@ namespace BukiVedi.App.Controllers
return Ok(); return Ok();
} }
[HttpPost("/api/books/{id}/read")] /// <summary>
public async Task<ActionResult<IEnumerable<BookResponse>>> AddBookToReadingQueue([FromRoute] string id) /// Добавление книги в очередь на чтение
/// </summary>
/// <param name="id">Идентификатор книги</param>
/// <returns>Ok</returns>
[HttpPost("{id}/read")]
public async Task<IActionResult> AddBookToReadingQueue([FromRoute] string id)
{ {
if (await Tables.Books.ExistById(id)) if (await Tables.Books.ExistById(id))
{ {
@ -130,15 +239,12 @@ namespace BukiVedi.App.Controllers
return Ok(); return Ok();
} }
/// <summary>
[HttpPost("/api/books/author/{id}")] /// Загрузка файла с книгой
public async Task<ActionResult<IEnumerable<BookResponse>>> AiSearch([FromRoute] string id) /// </summary>
{ /// <param name="id">Идентификатор книги</param>
var books = (await _library.SearchBooksByAuthor(id)).ToArray(); /// <returns>Файл</returns>
return Ok(books.Select(b => BookEntityMapper.Map(b))); [HttpGet("download/{id}")]
}
[HttpGet("/api/books/download/{id}")]
public async Task<IActionResult> GetBlobDownload([FromRoute] string id) public async Task<IActionResult> GetBlobDownload([FromRoute] string id)
{ {
var content = new System.IO.MemoryStream(); var content = new System.IO.MemoryStream();

@ -0,0 +1,32 @@
using BukiVedi.Shared.Entities;
using BukiVedi.Shared.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using MongoDB.Driver;
namespace BukiVedi.App.Controllers
{
[Route("api/hints")]
[ApiController]
[Authorize("authorized")]
public class HintsController
: BaseController
{
private readonly ILibrary _library;
public HintsController(ILibrary library)
: base()
{
_library = library;
}
/// <summary>
/// Список пользовательских тегов
/// </summary>
/// <returns></returns>
[HttpGet("tags")]
public async Task<ActionResult<IEnumerable<string>>> GetUserTags()
{
return Ok((await Tables.UserTag.Get(Builders<UserTag>.Filter.Eq(t => t.UserId, OperationContext.OperationInitiator.Id)))?.Select(t => t.Name));
}
}
}

@ -5,7 +5,7 @@ https://go.microsoft.com/fwlink/?LinkID=208121.
<Project> <Project>
<PropertyGroup> <PropertyGroup>
<_PublishTargetUrl>G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Release\net8.0\publish\</_PublishTargetUrl> <_PublishTargetUrl>G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Release\net8.0\publish\</_PublishTargetUrl>
<History>True|2024-04-05T01:52:06.7814045Z;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-04-07T02:01:48.6765910Z;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 /> <LastFailureDetails />
</PropertyGroup> </PropertyGroup>
</Project> </Project>

@ -67,12 +67,11 @@
/// Год издания /// Год издания
/// </summary> /// </summary>
public int Year { get; set; } public int Year { get; set; }
/*
/// <summary>
/// Форматы(массив объектов с полями id; имя формата)
/// </summary>
public FormatInfo[] Formats { get; set; }
*/
public string Format { get; set; } public string Format { get; set; }
public bool IsBlocked { get; set; }
public bool IsFavorite { get; set; }
} }
} }

@ -1,401 +0,0 @@
{
"runtimeTarget": {
"name": ".NETCoreApp,Version=v8.0",
"signature": ""
},
"compilationOptions": {},
"targets": {
".NETCoreApp,Version=v8.0": {
"BukiVedi.App/1.0.0": {
"dependencies": {
"BukiVedi.Shared": "1.0.0"
},
"runtime": {
"BukiVedi.App.dll": {}
}
},
"AWSSDK.Core/3.7.100.14": {
"runtime": {
"lib/netcoreapp3.1/AWSSDK.Core.dll": {
"assemblyVersion": "3.3.0.0",
"fileVersion": "3.7.100.14"
}
}
},
"AWSSDK.SecurityToken/3.7.100.14": {
"dependencies": {
"AWSSDK.Core": "3.7.100.14"
},
"runtime": {
"lib/netcoreapp3.1/AWSSDK.SecurityToken.dll": {
"assemblyVersion": "3.3.0.0",
"fileVersion": "3.7.100.14"
}
}
},
"DnsClient/1.6.1": {
"dependencies": {
"Microsoft.Win32.Registry": "5.0.0"
},
"runtime": {
"lib/net5.0/DnsClient.dll": {
"assemblyVersion": "1.6.1.0",
"fileVersion": "1.6.1.0"
}
}
},
"FB2Library/1.3.3": {
"runtime": {
"lib/net6.0/FB2Library.dll": {
"assemblyVersion": "1.3.3.0",
"fileVersion": "1.3.3.0"
}
}
},
"Microsoft.Extensions.Logging.Abstractions/2.0.0": {},
"Microsoft.NETCore.Platforms/5.0.0": {},
"Microsoft.Win32.Registry/5.0.0": {
"dependencies": {
"System.Security.AccessControl": "5.0.0",
"System.Security.Principal.Windows": "5.0.0"
}
},
"MongoDB.Bson/2.24.0": {
"dependencies": {
"System.Memory": "4.5.5",
"System.Runtime.CompilerServices.Unsafe": "5.0.0"
},
"runtime": {
"lib/netstandard2.1/MongoDB.Bson.dll": {
"assemblyVersion": "2.24.0.0",
"fileVersion": "2.24.0.0"
}
}
},
"MongoDB.Driver/2.24.0": {
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "2.0.0",
"MongoDB.Bson": "2.24.0",
"MongoDB.Driver.Core": "2.24.0",
"MongoDB.Libmongocrypt": "1.8.2"
},
"runtime": {
"lib/netstandard2.1/MongoDB.Driver.dll": {
"assemblyVersion": "2.24.0.0",
"fileVersion": "2.24.0.0"
}
}
},
"MongoDB.Driver.Core/2.24.0": {
"dependencies": {
"AWSSDK.SecurityToken": "3.7.100.14",
"DnsClient": "1.6.1",
"Microsoft.Extensions.Logging.Abstractions": "2.0.0",
"MongoDB.Bson": "2.24.0",
"MongoDB.Libmongocrypt": "1.8.2",
"SharpCompress": "0.30.1",
"Snappier": "1.0.0",
"System.Buffers": "4.5.1",
"ZstdSharp.Port": "0.7.3"
},
"runtime": {
"lib/netstandard2.1/MongoDB.Driver.Core.dll": {
"assemblyVersion": "2.24.0.0",
"fileVersion": "2.24.0.0"
}
}
},
"MongoDB.Libmongocrypt/1.8.2": {
"runtime": {
"lib/netstandard2.1/MongoDB.Libmongocrypt.dll": {
"assemblyVersion": "1.8.2.0",
"fileVersion": "1.8.2.0"
}
},
"runtimeTargets": {
"runtimes/linux/native/libmongocrypt.so": {
"rid": "linux",
"assetType": "native",
"fileVersion": "0.0.0.0"
},
"runtimes/osx/native/libmongocrypt.dylib": {
"rid": "osx",
"assetType": "native",
"fileVersion": "0.0.0.0"
},
"runtimes/win/native/mongocrypt.dll": {
"rid": "win",
"assetType": "native",
"fileVersion": "0.0.0.0"
}
}
},
"SharpCompress/0.30.1": {
"runtime": {
"lib/net5.0/SharpCompress.dll": {
"assemblyVersion": "0.30.1.0",
"fileVersion": "0.30.1.0"
}
}
},
"Snappier/1.0.0": {
"runtime": {
"lib/net5.0/Snappier.dll": {
"assemblyVersion": "1.0.0.0",
"fileVersion": "1.0.0.0"
}
}
},
"System.Buffers/4.5.1": {},
"System.Memory/4.5.5": {},
"System.Runtime.CompilerServices.Unsafe/5.0.0": {},
"System.Security.AccessControl/5.0.0": {
"dependencies": {
"Microsoft.NETCore.Platforms": "5.0.0",
"System.Security.Principal.Windows": "5.0.0"
}
},
"System.Security.Principal.Windows/5.0.0": {},
"ZstdSharp.Port/0.7.3": {
"runtime": {
"lib/net7.0/ZstdSharp.dll": {
"assemblyVersion": "0.7.3.0",
"fileVersion": "0.7.3.0"
}
}
},
"BukiVedi.Shared/1.0.0": {
"dependencies": {
"FB2Library": "1.3.3",
"LemmaSharp": "1.0.0",
"LemmaSharpPrebuilt": "1.0.0",
"LemmaSharpPrebuiltFull": "1.0.0",
"MongoDB.Driver": "2.24.0",
"Sleopok.Engine": "1.0.0",
"ZeroLevel": "3.4.0.8"
},
"runtime": {
"BukiVedi.Shared.dll": {}
}
},
"LemmaSharp/1.0.0": {
"runtime": {
"LemmaSharp.dll": {}
}
},
"LemmaSharpPrebuilt/1.0.0": {
"dependencies": {
"LemmaSharp": "1.0.0"
},
"runtime": {
"LemmaSharpPrebuilt.dll": {}
}
},
"LemmaSharpPrebuiltFull/1.0.0": {
"dependencies": {
"LemmaSharp": "1.0.0",
"LemmaSharpPrebuilt": "1.0.0"
},
"runtime": {
"LemmaSharpPrebuiltFull.dll": {}
}
},
"Sleopok.Engine/1.0.0": {
"dependencies": {
"ZeroLevel": "3.4.0.8"
},
"runtime": {
"Sleopok.Engine.dll": {}
}
},
"ZeroLevel/3.4.0.8": {
"runtime": {
"ZeroLevel.dll": {}
}
},
"Lzma#/4.12.3884.11200": {
"runtime": {
"Lzma#.dll": {
"assemblyVersion": "4.12.3884.11200",
"fileVersion": "4.12.3884.11200"
}
}
}
}
},
"libraries": {
"BukiVedi.App/1.0.0": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"AWSSDK.Core/3.7.100.14": {
"type": "package",
"serviceable": true,
"sha512": "sha512-gnEgxBlk4PFEfdPE8Lkf4+D16MZFYSaW7/o6Wwe5e035QWUkTJX0Dn4LfTCdV5QSEL/fOFxu+yCAm55eIIBgog==",
"path": "awssdk.core/3.7.100.14",
"hashPath": "awssdk.core.3.7.100.14.nupkg.sha512"
},
"AWSSDK.SecurityToken/3.7.100.14": {
"type": "package",
"serviceable": true,
"sha512": "sha512-dGCVuVo0CFUKWW85W8YENO+aREf8sCBDjvGbnNvxJuNW4Ss+brEU9ltHhq2KfZze2VUNK1/wygbPG1bmbpyXEw==",
"path": "awssdk.securitytoken/3.7.100.14",
"hashPath": "awssdk.securitytoken.3.7.100.14.nupkg.sha512"
},
"DnsClient/1.6.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-4H/f2uYJOZ+YObZjpY9ABrKZI+JNw3uizp6oMzTXwDw6F+2qIPhpRl/1t68O/6e98+vqNiYGu+lswmwdYUy3gg==",
"path": "dnsclient/1.6.1",
"hashPath": "dnsclient.1.6.1.nupkg.sha512"
},
"FB2Library/1.3.3": {
"type": "package",
"serviceable": true,
"sha512": "sha512-95eTqg5HBszY90+eZHcVLLFPWeHXV3S7gO6+VfrTdqq71uODj8+OaRRVXkTW7NPXxZ8QgJdZ7t4QaLZgoBES/A==",
"path": "fb2library/1.3.3",
"hashPath": "fb2library.1.3.3.nupkg.sha512"
},
"Microsoft.Extensions.Logging.Abstractions/2.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-6ZCllUYGFukkymSTx3Yr0G/ajRxoNJp7/FqSxSB4fGISST54ifBhgu4Nc0ItGi3i6DqwuNd8SUyObmiC++AO2Q==",
"path": "microsoft.extensions.logging.abstractions/2.0.0",
"hashPath": "microsoft.extensions.logging.abstractions.2.0.0.nupkg.sha512"
},
"Microsoft.NETCore.Platforms/5.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-VyPlqzH2wavqquTcYpkIIAQ6WdenuKoFN0BdYBbCWsclXacSOHNQn66Gt4z5NBqEYW0FAPm5rlvki9ZiCij5xQ==",
"path": "microsoft.netcore.platforms/5.0.0",
"hashPath": "microsoft.netcore.platforms.5.0.0.nupkg.sha512"
},
"Microsoft.Win32.Registry/5.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-dDoKi0PnDz31yAyETfRntsLArTlVAVzUzCIvvEDsDsucrl33Dl8pIJG06ePTJTI3tGpeyHS9Cq7Foc/s4EeKcg==",
"path": "microsoft.win32.registry/5.0.0",
"hashPath": "microsoft.win32.registry.5.0.0.nupkg.sha512"
},
"MongoDB.Bson/2.24.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-n8CWaA4iTuoEQYv0+FSKNTX/hJozFQa5EgSILVNPhTGHcrbABHhpVrT1NwRRAAS6sUb8ZyhHmLPBa88LJemptA==",
"path": "mongodb.bson/2.24.0",
"hashPath": "mongodb.bson.2.24.0.nupkg.sha512"
},
"MongoDB.Driver/2.24.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-j1q11iMk3LN38ze6jgV1ATp+WKVVQbsGrhFkuOcHwRNtIk70TpLKjOD1Z3CCkyrzxCsUyhwk745tK2ASNOI4WA==",
"path": "mongodb.driver/2.24.0",
"hashPath": "mongodb.driver.2.24.0.nupkg.sha512"
},
"MongoDB.Driver.Core/2.24.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-UW0yadpMPi9+MtLHy6onpol3D9tXMRg61P0ROnij+h35EOr0vt/nxvlPrDcUjl3SvttvpsEXQKxb2lQShBA1dA==",
"path": "mongodb.driver.core/2.24.0",
"hashPath": "mongodb.driver.core.2.24.0.nupkg.sha512"
},
"MongoDB.Libmongocrypt/1.8.2": {
"type": "package",
"serviceable": true,
"sha512": "sha512-z/8JCULSHM1+mzkau0ivIkU9kIn8JEFFSkmYTSaMaWMMHt96JjUtMKuXxeGNGSnHZ5290ZPKIlQfjoWFk2sKog==",
"path": "mongodb.libmongocrypt/1.8.2",
"hashPath": "mongodb.libmongocrypt.1.8.2.nupkg.sha512"
},
"SharpCompress/0.30.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-XqD4TpfyYGa7QTPzaGlMVbcecKnXy4YmYLDWrU+JIj7IuRNl7DH2END+Ll7ekWIY8o3dAMWLFDE1xdhfIWD1nw==",
"path": "sharpcompress/0.30.1",
"hashPath": "sharpcompress.0.30.1.nupkg.sha512"
},
"Snappier/1.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-rFtK2KEI9hIe8gtx3a0YDXdHOpedIf9wYCEYtBEmtlyiWVX3XlCNV03JrmmAi/Cdfn7dxK+k0sjjcLv4fpHnqA==",
"path": "snappier/1.0.0",
"hashPath": "snappier.1.0.0.nupkg.sha512"
},
"System.Buffers/4.5.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-Rw7ijyl1qqRS0YQD/WycNst8hUUMgrMH4FCn1nNm27M4VxchZ1js3fVjQaANHO5f3sN4isvP4a+Met9Y4YomAg==",
"path": "system.buffers/4.5.1",
"hashPath": "system.buffers.4.5.1.nupkg.sha512"
},
"System.Memory/4.5.5": {
"type": "package",
"serviceable": true,
"sha512": "sha512-XIWiDvKPXaTveaB7HVganDlOCRoj03l+jrwNvcge/t8vhGYKvqV+dMv6G4SAX2NoNmN0wZfVPTAlFwZcZvVOUw==",
"path": "system.memory/4.5.5",
"hashPath": "system.memory.4.5.5.nupkg.sha512"
},
"System.Runtime.CompilerServices.Unsafe/5.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-ZD9TMpsmYJLrxbbmdvhwt9YEgG5WntEnZ/d1eH8JBX9LBp+Ju8BSBhUGbZMNVHHomWo2KVImJhTDl2hIgw/6MA==",
"path": "system.runtime.compilerservices.unsafe/5.0.0",
"hashPath": "system.runtime.compilerservices.unsafe.5.0.0.nupkg.sha512"
},
"System.Security.AccessControl/5.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-dagJ1mHZO3Ani8GH0PHpPEe/oYO+rVdbQjvjJkBRNQkX4t0r1iaeGn8+/ybkSLEan3/slM0t59SVdHzuHf2jmw==",
"path": "system.security.accesscontrol/5.0.0",
"hashPath": "system.security.accesscontrol.5.0.0.nupkg.sha512"
},
"System.Security.Principal.Windows/5.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-t0MGLukB5WAVU9bO3MGzvlGnyJPgUlcwerXn1kzBRjwLKixT96XV0Uza41W49gVd8zEMFu9vQEFlv0IOrytICA==",
"path": "system.security.principal.windows/5.0.0",
"hashPath": "system.security.principal.windows.5.0.0.nupkg.sha512"
},
"ZstdSharp.Port/0.7.3": {
"type": "package",
"serviceable": true,
"sha512": "sha512-U9Ix4l4cl58Kzz1rJzj5hoVTjmbx1qGMwzAcbv1j/d3NzrFaESIurQyg+ow4mivCgkE3S413y+U9k4WdnEIkRA==",
"path": "zstdsharp.port/0.7.3",
"hashPath": "zstdsharp.port.0.7.3.nupkg.sha512"
},
"BukiVedi.Shared/1.0.0": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"LemmaSharp/1.0.0": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"LemmaSharpPrebuilt/1.0.0": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"LemmaSharpPrebuiltFull/1.0.0": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"Sleopok.Engine/1.0.0": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"ZeroLevel/3.4.0.8": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"Lzma#/4.12.3884.11200": {
"type": "reference",
"serviceable": false,
"sha512": ""
}
}
}

@ -1,19 +0,0 @@
{
"runtimeOptions": {
"tfm": "net8.0",
"frameworks": [
{
"name": "Microsoft.NETCore.App",
"version": "8.0.0"
},
{
"name": "Microsoft.AspNetCore.App",
"version": "8.0.0"
}
],
"configProperties": {
"System.GC.Server": true,
"System.Runtime.Serialization.EnableUnsafeBinaryFormatterSerialization": false
}
}
}

@ -1,3 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8"/></startup></configuration>

@ -1,3 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8"/></startup></configuration>

@ -1,3 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8"/></startup></configuration>

@ -1,8 +0,0 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}

@ -1,16 +0,0 @@
{
"Kestrel": {
"Endpoints": {
"MyHttpEndpoint": {
"Url": "http://0.0.0.0:80"
}
}
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}

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

@ -1,316 +0,0 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>BukiVedi</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" />
<link href="css/buki-common.css" rel="stylesheet" />
<script src="js/jquery.js"></script>
<script src="js/bukivedi.js"></script>
<style>
html,
body {
height: 100%;
}
body {
margin: 0px;
padding: 0px;
line-height: 1;
width: 100%;
min-height: 100%;
height: 100%;
font-weight: 300;
background-color: #19272e;
color: #3f5562;
}
#search {
display: block;
margin-top: 20px;
margin-left: auto;
margin-right: auto;
max-width: 820px;
min-width: 160px;
width: 100%;
height: 28px;
font-size: 18px;
padding-left: 6px;
}
#searchButton {
display: block;
margin-top: 10px;
margin-left: auto;
margin-right: auto;
max-width: 200px;
width: 200px;
min-width: 80px;
height: 33px;
}
#content {
margin-top: 40px;
margin-left: auto;
margin-right: auto;
max-width: 820px;
width: 100%;
}
/*========================================================
Book Section
========================================================*/
a {
text-decoration: none;
}
.card {
min-height: 30px;
margin-bottom: 15px;
background: #fff;
border-radius: 5px;
border: 1px solid #e7eaee;
position: relative;
padding: 10px;
width: 96%;
background-color: #f3f4f5;
}
.card .desc {
display: block;
max-height: 120px;
overflow: auto;
margin: 3px;
text-align: justify;
font-size: 14px;
}
.card .card-circle {
float: left;
height: 20px;
width: 20px;
margin: 10px 12px 18px 5px;
border-radius: 20px;
border: 1px solid #8cd9a0;
background: #dff5ee;
}
.card p {
padding: 5px;
font-size: 16px;
line-height: 18px;
}
.card .author {
margin-left: 30px;
padding-bottom: 5px;
color: #06001aff;
width: 100%;
}
.card .unassigned {
color: #f29840;
}
.card .due {
color: #ec7373;
}
.menu {
visibility: hidden;
z-index: 1000;
position: relative;
height: 0;
background-color: #171717;
}
.open-menu {
text-decoration: none;
font-size: 18px;
font-weight: bolder;
}
.menu.opened {
visibility: visible;
color: azure;
width: 180px;
}
.menu-item {
text-decoration: none;
background-color: #272727;
height: 28px;
width: 100%;
text-align: left;
padding-top: 12px;
padding-left: 16px;
cursor: pointer;
}
.menu-item:hover {
background-color: #373737;
}
ul {
list-style-type: none;
}
</style>
</head>
<body>
<h1 class="background-logo">BukiVedi</h1>
<input id="search">
<button id="searchButton" onclick="search(document.getElementById('search').value);">Поиск</button>
<div id="content">
<div id="books"></div>
</div>
<script>
const MenuActions =
{
AddToFavorite: '0',
ToReadingQueue: '1',
BookBlock: '2',
AuthorBlock: '3',
Tag: '4',
Note: '5',
Share: '6'
};
function Tag(id) { }
function Note(id) { }
function Share(id) { }
function eraseCookie(name) {
document.cookie = name + '=; Max-Age=-99999999;';
}
function bindMenuButton(menuId, buttonId) {
var openMenuBtn = document.getElementById(buttonId);
openMenuBtn.addEventListener('click', function (e) {
e.preventDefault();
var menu = document.getElementById(menuId);
menu.classList.toggle('opened');
}, false);
//window.addEventListener('click', function (e) { if (menu.classList.contains('opened') && !document.getElementById('menu').contains(e.target) && !document.getElementById('menuBtn').contains(e.target)) { menu.classList.toggle('opened'); } })
}
function proceedMenuAction(bookId, menuId, actionType) {
var menu = document.getElementById(menuId);
menu.classList.toggle('opened');
switch (actionType) {
case MenuActions.AddToFavorite:
BukiVedi.AddToFavorite(bookId);
break;
case MenuActions.ToReadingQueue:
BukiVedi.ToReadingQueue(bookId);
break;
case MenuActions.BookBlock:
BukiVedi.BookBlock(bookId);
break;
case MenuActions.AuthorBlock:
BukiVedi.AuthorBlock(bookId);
break;
case MenuActions.Tag:
Tag(bookId);
break;
case MenuActions.Note:
Note(bookId);
break;
case MenuActions.Share:
Share(bookId);
break;
}
}
function appendBooksToContent(books) {
$("#books").empty();
for (var idx in books) {
const data = books[idx];
let id = data.id;
//автор
var authorLinks = [];
if (data.authors.length > 0) {
for (idx in data.authors) {
author = data.authors[idx].name;
author_id = data.authors[idx].id;
authorLinks.push("<a onclick=\"BukiVedi.SearchByAuthor('" + author_id + "', appendBooksToContent)\">" + author + "</a>");
authorLinks.push("<strong>;</strong>");
}
}
// Жанр
let genre = '--';
if (data.genres.length > 0) {
genre = data.genres[0].name;
}
if (genre == null) genre = '--';
let menuId = "menu_" + id;
let btnId = "menuBtn_" + id;
$('#books').append(
$("<div class='card'>"
+ "<a onclick=\"BukiVedi.Download('" + id + "')\">"
+ "<div class='card-circle'></div>"
+ "</a>"
+ "<div style='display: float;'>"
+ "<a id='"
+ btnId
+ "' href='#' class='open-menu'>···</a>"
+ "<nav id='"
+ menuId
+ "' class='menu'><ul>"
+ "<li onclick=\"proceedMenuAction('" + id + "', '" + menuId + "', '" + MenuActions.AddToFavorite + "')\" class='menu-item'>В избранное</li>"
+ "<li onclick=\"proceedMenuAction('" + id + "', '" + menuId + "', '" + MenuActions.ToReadingQueue + "')\"class='menu-item'>В очередь на чтение</li>"
+ "<li onclick=\"proceedMenuAction('" + id + "', '" + menuId + "', '" + MenuActions.BookBlock + "')\"class='menu-item'>Игнорировать</li>"
+ "<li onclick=\"proceedMenuAction('" + id + "', '" + menuId + "', '" + MenuActions.AuthorBlock + "')\"class='menu-item'>Игнорировать автора</li>"
+ "<li onclick=\"proceedMenuAction('" + id + "', '" + menuId + "', '" + MenuActions.Tag + "')\"class='menu-item'>Теги</li>"
+ "<li onclick=\"proceedMenuAction('" + id + "', '" + menuId + "', '" + MenuActions.Note + "')\"class='menu-item'>Заметка</li>"
+ "<li onclick=\"proceedMenuAction('" + id + "', '" + menuId + "', '" + MenuActions.Share + "')\"class='menu-item'>Поделиться</li>"
+ "</ul></nav>"
+ "</div>"
+ "<p class='author'>"
+ authorLinks.join("")
+ "<string> · </string><span class='due'>"
+ genre
+ "</span>"
+ "</p>"
+ "<p>"
+ data.title
+ "</p>"
+ "<p class='desc'>"
+ data.description
+ "</p>"
+ "</div>")
);
bindMenuButton(menuId, btnId);
}
}
function search(searchText) {
BukiVedi.Search(searchText, books => appendBooksToContent(books));
}
$(() => {
var input = document.getElementById("search");
input.addEventListener("keypress", function (event) {
if (event.key === "Enter") {
event.preventDefault();
document.getElementById("searchButton").click();
}
});
});
</script>
</body>
</html>

@ -1,25 +0,0 @@
class BukiVediAuth {
static _token_name = "X-Token";
static SignIn(login, password, success) {
const info = { "Login": login, "Password": password };
$.ajax({
contentType: "application/json; charset=utf-8",
dataType: "json",
type: "POST",
url: "../api/auth",
data: JSON.stringify(info),
success: function (data, textStatus, jqXHR) {
success(data);
},
error: function (jqXHR, textStatus, errorThrown) {
console.log(jqXHR.statusText);
}
});
};
static Logout() {
localStorage.removeItem(this._token_name);
window.location.replace("web/login.html");
};
}

@ -1,95 +0,0 @@
class BukiVedi {
static SearchByAuthor(id, success) {
$.ajax({
contentType: "application/json; charset=utf-8",
type: "POST",
url: "../api/books/search/author/" + id,
success: function (data, textStatus, jqXHR) {
success(data);
},
error: function (jqXHR, textStatus, errorThrown) {
console.log(jqXHR.statusText);
}
});
}
static Search(query, success) {
const info = { "query": query };
$.ajax({
contentType: "application/json; charset=utf-8",
dataType: "json",
type: "POST",
url: "../api/books/search",
data: JSON.stringify(info),
success: function (data, textStatus, jqXHR) {
success(data);
},
error: function (jqXHR, textStatus, errorThrown) {
console.log(jqXHR.statusText);
}
});
};
static Download(id) {
window.location.href = "../api/books/download/" + id;
}
static AddToFavorite(id, success) {
$.ajax({
type: "POST",
url: "../api/books/" + id + "/favorite",
success: function (data, textStatus, jqXHR) {
if (success)
success();
},
error: function (jqXHR, textStatus, errorThrown) {
console.log(jqXHR.statusText);
}
});
}
static ToReadingQueue(id) {
$.ajax({
type: "POST",
url: "../api/books/" + id + "/read",
success: function (data, textStatus, jqXHR) {
if (success)
success();
},
error: function (jqXHR, textStatus, errorThrown) {
console.log(jqXHR.statusText);
}
});
}
static BookBlock(id) {
$.ajax({
type: "POST",
url: "../api/books/" + id + "/block",
success: function (data, textStatus, jqXHR) {
if (success)
success();
},
error: function (jqXHR, textStatus, errorThrown) {
console.log(jqXHR.statusText);
}
});
}
static AuthorBlock(id) {
$.ajax({
type: "POST",
url: "../api/books/" + id + "/author/block",
success: function (data, textStatus, jqXHR) {
if (success)
success();
},
error: function (jqXHR, textStatus, errorThrown) {
console.log(jqXHR.statusText);
}
});
}
static Logout() {
localStorage.removeItem(this._token_name);
window.location.replace("web/login.html");
};
}

File diff suppressed because it is too large Load Diff

@ -1,120 +0,0 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>BukiVedi - Sign In</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" />
<link href="css/buki-common.css" rel="stylesheet" />
<script src="js/jquery.js"></script>
<script src="js/bukivedi-auth.js"></script>
<style>
html,
body {
margin: 0;
display: flex;
align-items: center;
justify-content: center;
min-height: 100vh;
background: #fafafa;
color: #333;
}
.central {
width: 400px;
height: 300px;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: auto;
}
.container {
width: 100%;
max-width: 400px;
}
.card {
width: 100%;
background-color: #f8f8f8;
padding: 20px;
border-radius: 12px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}
h2 {
text-align: center;
color: #333;
}
.form {
display: flex;
flex-direction: column;
}
input {
padding: 10px;
margin-bottom: 12px;
border: 2px solid #ddd;
border-radius: 8px;
transition: border-color 0.3s ease-in-out;
outline: none;
color: #333;
background-color: #f4f4f4;
}
input:focus {
border-color: #ff9900;
}
button {
background-color: #ff9900;
color: #fff;
padding: 10px;
border: none;
border-radius: 8px;
cursor: pointer;
transition: background-color 0.3s ease-in-out;
}
button:hover {
background-color: #ff6600;
}
</style>
</head>
<body>
<div class="container central">
<div class="card">
<h2>Login</h2>
<div class="form">
<input type="text" id="login" name="username" placeholder="Username" required>
<input type="password" id="password" name="password" placeholder="Password" required>
<button id="button" onclick="login()">Login</button>
</div>
</div>
</div>
<script>
function login() {
const name = document.getElementById('login').value;
const pwd = document.getElementById('password').value;
BukiVediAuth.SignIn(name, pwd, (data) => {
if (data.success == true) {
window.location.replace("index.html");
}
else {
alert("Account not found");
}
});
}
</script>
</body>
</html>

@ -35,22 +35,16 @@
] ]
}, },
{ {
"ContainingType": "BukiVedi.App.Controllers.BooksController", "ContainingType": "BukiVedi.App.Controllers.AuthorsController",
"Method": "BlockBookAuthor", "Method": "GetAllAuthors",
"RelativePath": "api/books/{id}/author/block", "RelativePath": "api/author",
"HttpMethod": "POST", "HttpMethod": "GET",
"IsController": true, "IsController": true,
"Order": 0, "Order": 0,
"Parameters": [ "Parameters": [],
{
"Name": "id",
"Type": "System.String",
"IsRequired": true
}
],
"ReturnTypes": [ "ReturnTypes": [
{ {
"Type": "System.Collections.Generic.IEnumerable\u00601[[BukiVedi.App.Responces.BookResponse, BukiVedi.App, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]", "Type": "System.Collections.Generic.IEnumerable\u00601[[BukiVedi.App.Responces.AuthorInfo, BukiVedi.App, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]",
"MediaTypes": [ "MediaTypes": [
"text/plain", "text/plain",
"application/json", "application/json",
@ -61,9 +55,9 @@
] ]
}, },
{ {
"ContainingType": "BukiVedi.App.Controllers.BooksController", "ContainingType": "BukiVedi.App.Controllers.AuthorsController",
"Method": "BlockBook", "Method": "SearchByAuthor",
"RelativePath": "api/books/{id}/block", "RelativePath": "api/author/{id}/books",
"HttpMethod": "POST", "HttpMethod": "POST",
"IsController": true, "IsController": true,
"Order": 0, "Order": 0,
@ -86,10 +80,30 @@
} }
] ]
}, },
{
"ContainingType": "BukiVedi.App.Controllers.AuthorsController",
"Method": "GetFavoriteAuthors",
"RelativePath": "api/author/favorite",
"HttpMethod": "GET",
"IsController": true,
"Order": 0,
"Parameters": [],
"ReturnTypes": [
{
"Type": "System.Collections.Generic.IEnumerable\u00601[[BukiVedi.App.Responces.AuthorInfo, BukiVedi.App, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]",
"MediaTypes": [
"text/plain",
"application/json",
"text/json"
],
"StatusCode": 200
}
]
},
{ {
"ContainingType": "BukiVedi.App.Controllers.BooksController", "ContainingType": "BukiVedi.App.Controllers.BooksController",
"Method": "AddToFavorite", "Method": "BlockBookAuthor",
"RelativePath": "api/books/{id}/favorite", "RelativePath": "api/books/{id}/author/block",
"HttpMethod": "POST", "HttpMethod": "POST",
"IsController": true, "IsController": true,
"Order": 0, "Order": 0,
@ -114,8 +128,8 @@
}, },
{ {
"ContainingType": "BukiVedi.App.Controllers.BooksController", "ContainingType": "BukiVedi.App.Controllers.BooksController",
"Method": "AddBookToReadingQueue", "Method": "AddAuthorsToFavorite",
"RelativePath": "api/books/{id}/read", "RelativePath": "api/books/{id}/authors/favorite",
"HttpMethod": "POST", "HttpMethod": "POST",
"IsController": true, "IsController": true,
"Order": 0, "Order": 0,
@ -126,22 +140,28 @@
"IsRequired": true "IsRequired": true
} }
], ],
"ReturnTypes": [ "ReturnTypes": []
},
{
"ContainingType": "BukiVedi.App.Controllers.BooksController",
"Method": "BlockBook",
"RelativePath": "api/books/{id}/block",
"HttpMethod": "POST",
"IsController": true,
"Order": 0,
"Parameters": [
{ {
"Type": "System.Collections.Generic.IEnumerable\u00601[[BukiVedi.App.Responces.BookResponse, BukiVedi.App, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]", "Name": "id",
"MediaTypes": [ "Type": "System.String",
"text/plain", "IsRequired": true
"application/json",
"text/json"
],
"StatusCode": 200
} }
] ],
"ReturnTypes": []
}, },
{ {
"ContainingType": "BukiVedi.App.Controllers.BooksController", "ContainingType": "BukiVedi.App.Controllers.BooksController",
"Method": "AiSearch", "Method": "AddToFavorite",
"RelativePath": "api/books/author/{id}", "RelativePath": "api/books/{id}/favorite",
"HttpMethod": "POST", "HttpMethod": "POST",
"IsController": true, "IsController": true,
"Order": 0, "Order": 0,
@ -152,17 +172,23 @@
"IsRequired": true "IsRequired": true
} }
], ],
"ReturnTypes": [ "ReturnTypes": []
},
{
"ContainingType": "BukiVedi.App.Controllers.BooksController",
"Method": "AddBookToReadingQueue",
"RelativePath": "api/books/{id}/read",
"HttpMethod": "POST",
"IsController": true,
"Order": 0,
"Parameters": [
{ {
"Type": "System.Collections.Generic.IEnumerable\u00601[[BukiVedi.App.Responces.BookResponse, BukiVedi.App, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]", "Name": "id",
"MediaTypes": [ "Type": "System.String",
"text/plain", "IsRequired": true
"application/json",
"text/json"
],
"StatusCode": 200
} }
] ],
"ReturnTypes": []
}, },
{ {
"ContainingType": "BukiVedi.App.Controllers.BooksController", "ContainingType": "BukiVedi.App.Controllers.BooksController",
@ -207,22 +233,16 @@
] ]
}, },
{ {
"ContainingType": "BukiVedi.App.Controllers.BooksController", "ContainingType": "BukiVedi.App.Controllers.HintsController",
"Method": "SearchByAuthor", "Method": "GetUserTags",
"RelativePath": "api/books/search/author/{id}", "RelativePath": "api/hints/tags",
"HttpMethod": "POST", "HttpMethod": "GET",
"IsController": true, "IsController": true,
"Order": 0, "Order": 0,
"Parameters": [ "Parameters": [],
{
"Name": "id",
"Type": "System.String",
"IsRequired": true
}
],
"ReturnTypes": [ "ReturnTypes": [
{ {
"Type": "System.Collections.Generic.IEnumerable\u00601[[BukiVedi.App.Responces.BookResponse, BukiVedi.App, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]", "Type": "System.Collections.Generic.IEnumerable\u00601[[System.String, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]",
"MediaTypes": [ "MediaTypes": [
"text/plain", "text/plain",
"application/json", "application/json",

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

@ -1 +1 @@
a4008023d611329de19eb93895353fbf5436c04f519c836afe3257e02cb5c27f e5a3d294f67b6f7db5ed4106b1e0779f1ab92391b34c7101aef3389c854bc7ea

@ -1 +1 @@
9ab24c09132cac03e148ed49c9192a73ea2f7e25169eea5eed0ebf606d46423e 4c4f32f8e585faf173948396d852ab461832b5dd36928e2eae2b6a67ddba0a04

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

@ -1 +1 @@
f411778caf5feb253bfafb32077ff4ee35f44944300272121ab4649fc28e757c 7df96b43abebe45316492c0eab3b2a931f2ab369acddd345785691bd9a0f5bb0

@ -1 +1 @@
f47297bb75113fc14623e9bec544ad02bf5686dd6d87602d151c32c708a7f891 77b8edc61e845321985d3d19a39d8162ddb364e5c54da6d70318f8cf097ee2bd

@ -175,12 +175,13 @@
const MenuActions = const MenuActions =
{ {
AddToFavorite: '0', AddToFavorite: '0',
ToReadingQueue: '1', AddAuthorsToFavorite: '1',
BookBlock: '2', ToReadingQueue: '2',
AuthorBlock: '3', BookBlock: '3',
Tag: '4', AuthorBlock: '4',
Note: '5', Tag: '5',
Share: '6' Note: '6',
Share: '7'
}; };
function Tag(id) { } function Tag(id) { }
@ -208,6 +209,9 @@
case MenuActions.AddToFavorite: case MenuActions.AddToFavorite:
BukiVedi.AddToFavorite(bookId); BukiVedi.AddToFavorite(bookId);
break; break;
case MenuActions.AddAuthorsToFavorite:
BukiVedi.AddAuthorsToFavorite(bookId);
break;
case MenuActions.ToReadingQueue: case MenuActions.ToReadingQueue:
BukiVedi.ToReadingQueue(bookId); BukiVedi.ToReadingQueue(bookId);
break; break;
@ -270,6 +274,7 @@
+ menuId + menuId
+ "' class='menu'><ul>" + "' class='menu'><ul>"
+ "<li onclick=\"proceedMenuAction('" + id + "', '" + menuId + "', '" + MenuActions.AddToFavorite + "')\" class='menu-item'>В избранное</li>" + "<li onclick=\"proceedMenuAction('" + id + "', '" + menuId + "', '" + MenuActions.AddToFavorite + "')\" class='menu-item'>В избранное</li>"
+ "<li onclick=\"proceedMenuAction('" + id + "', '" + menuId + "', '" + MenuActions.AddAuthorsToFavorite + "')\" class='menu-item'>Авторов в избранное</li>"
+ "<li onclick=\"proceedMenuAction('" + id + "', '" + menuId + "', '" + MenuActions.ToReadingQueue + "')\"class='menu-item'>В очередь на чтение</li>" + "<li onclick=\"proceedMenuAction('" + id + "', '" + menuId + "', '" + MenuActions.ToReadingQueue + "')\"class='menu-item'>В очередь на чтение</li>"
+ "<li onclick=\"proceedMenuAction('" + id + "', '" + menuId + "', '" + MenuActions.BookBlock + "')\"class='menu-item'>Игнорировать</li>" + "<li onclick=\"proceedMenuAction('" + id + "', '" + menuId + "', '" + MenuActions.BookBlock + "')\"class='menu-item'>Игнорировать</li>"
+ "<li onclick=\"proceedMenuAction('" + id + "', '" + menuId + "', '" + MenuActions.AuthorBlock + "')\"class='menu-item'>Игнорировать автора</li>" + "<li onclick=\"proceedMenuAction('" + id + "', '" + menuId + "', '" + MenuActions.AuthorBlock + "')\"class='menu-item'>Игнорировать автора</li>"

@ -4,7 +4,7 @@
$.ajax({ $.ajax({
contentType: "application/json; charset=utf-8", contentType: "application/json; charset=utf-8",
type: "POST", type: "POST",
url: "../api/books/search/author/" + id, url: "../api/author/" + id+"/books",
success: function (data, textStatus, jqXHR) { success: function (data, textStatus, jqXHR) {
success(data); success(data);
}, },
@ -48,6 +48,21 @@
} }
}); });
} }
static AddAuthorsToFavorite(id, success) {
$.ajax({
type: "POST",
url: "../api/books/" + id + "/authors/favorite",
success: function (data, textStatus, jqXHR) {
if (success)
success();
},
error: function (jqXHR, textStatus, errorThrown) {
console.log(jqXHR.statusText);
}
});
}
static ToReadingQueue(id) { static ToReadingQueue(id) {
$.ajax({ $.ajax({
type: "POST", type: "POST",

@ -1,8 +0,0 @@
namespace BukiVedi.Shared.Entities
{
public sealed class Tag
: BaseEntity
{
public string Name { get; set; }
}
}

@ -17,6 +17,6 @@
/// <summary> /// <summary>
/// Тег /// Тег
/// </summary> /// </summary>
public string TagId { get; set; } public string Name { get; set; }
} }
} }

@ -13,6 +13,11 @@ namespace BukiVedi.Shared.Services
{ {
Task<IEnumerable<BookEntity>> SearchBooksByAuthor(string author_id); Task<IEnumerable<BookEntity>> SearchBooksByAuthor(string author_id);
Task<IEnumerable<BookEntity>> SearchBooks(string title); Task<IEnumerable<BookEntity>> SearchBooks(string title);
Task<IEnumerable<BookEntity>> SearchTaggedBooks(string accountId, string tag = null!);
Task<IEnumerable<BookEntity>> SearchFavoritesBooks(string accountId);
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 DownloadToStream(Stream stream, string id);
} }
@ -58,25 +63,94 @@ namespace BukiVedi.Shared.Services
} }
} }
private async Task<IEnumerable<BookEntity>> PrepareBooksByFilter(FilterDefinition<Book> bookFilter)
{
var result = await Tables.Books.Get(bookFilter);
if (result != null && result.Any())
{
return result.Select(b => new BookEntity
{
Authors = GetAuthors(b),
Title = b.Title,
Year = b.Year,
Description = b.Description,
Format = b.Format,
Genre = new Genre(),
Id = b.Id,
});
}
return Enumerable.Empty<BookEntity>();
}
public async Task<IEnumerable<BookEntity>> SearchFavoritesBooks(string accountId)
{
IEnumerable<string> bookIds = (await Tables.FavoriteBooks.Get(Builders<FavoriteBook>.Filter.Eq(f => f.UserId, accountId)))?.Select(t => t.BookId)!;
if (bookIds != null && bookIds.Any())
{
var filter = Builders<Book>.Filter.In(b => b.Id, bookIds);
return await PrepareBooksByFilter(filter);
}
return Enumerable.Empty<BookEntity>();
}
public async Task<IEnumerable<BookEntity>> SearchToReadBooks(string accountId)
{
IEnumerable<string> bookIds = (await Tables.ReadQueue.Get(Builders<ReadQueueItem>.Filter.Eq(d => d.UserId, accountId)))?.Select(t => t.BookId)!;
if (bookIds != null && bookIds.Any())
{
var filter = Builders<Book>.Filter.In(b => b.Id, bookIds);
return await PrepareBooksByFilter(filter);
}
return Enumerable.Empty<BookEntity>();
}
public async Task<IEnumerable<BookEntity>> SearchBlockedBooks(string accountId)
{
IEnumerable<string> bookIds = (await Tables.DisgustingBooks.Get(Builders<DisgustingBook>.Filter.Eq(d => d.UserId, accountId)))?.Select(t => t.BookId)!;
if (bookIds != null && bookIds.Any())
{
var filter = Builders<Book>.Filter.In(b => b.Id, bookIds);
return await PrepareBooksByFilter(filter);
}
return Enumerable.Empty<BookEntity>();
}
public async Task<IEnumerable<BookEntity>> SearchFavoriteAuthorsBooks(string accountId)
{
var authorIds = (await Tables.FavoriteAuthors.Get(Builders<FavoriteAuthor>.Filter.Eq(f => f.UserId, accountId)))?.Select(t => t.AuthorId)?.ToHashSet();
if (authorIds != null && authorIds.Any())
{
var filter = Builders<Book>.Filter.AnyIn(b => b.AuthorIds, authorIds);
return await PrepareBooksByFilter(filter);
}
return Enumerable.Empty<BookEntity>();
}
public async Task<IEnumerable<BookEntity>> SearchBooksByAuthor(string author_id) public async Task<IEnumerable<BookEntity>> SearchBooksByAuthor(string author_id)
{ {
if (string.IsNullOrWhiteSpace(author_id) == false) if (string.IsNullOrWhiteSpace(author_id) == false)
{ {
var filter = Builders<Book>.Filter.AnyEq(b => b.AuthorIds, author_id); var filter = Builders<Book>.Filter.AnyEq(b => b.AuthorIds, author_id);
var result = await Tables.Books.Get(filter); return await PrepareBooksByFilter(filter);
if (result != null && result.Any()) }
{ return Enumerable.Empty<BookEntity>();
return result.Select(b => new BookEntity }
{
Authors = GetAuthors(b), public async Task<IEnumerable<BookEntity>> SearchTaggedBooks(string accountId, string tag = null)
Title = b.Title, {
Year = b.Year, IEnumerable<string> bookIds;
Description = b.Description, if (string.IsNullOrWhiteSpace(tag))
Format = b.Format, {
Genre = new Genre(), bookIds = (await Tables.UserTag.Get(Builders<UserTag>.Filter.Eq(t => t.UserId, accountId)))?.Select(t => t.BookId)!;
Id = b.Id, }
}); else
} {
bookIds = (await Tables.UserTag.Get(Builders<UserTag>.Filter.And(Builders<UserTag>.Filter.Eq(t => t.UserId, accountId), Builders<UserTag>.Filter.Eq(t => t.Name, tag))))?.Select(t => t.BookId)!;
}
if (bookIds != null && bookIds.Any())
{
var filter = Builders<Book>.Filter.In(b => b.Id, bookIds);
return await PrepareBooksByFilter(filter);
} }
return Enumerable.Empty<BookEntity>(); return Enumerable.Empty<BookEntity>();
} }

@ -14,7 +14,6 @@ namespace BukiVedi.Shared.Services
public static IRepository<Book> _books; public static IRepository<Book> _books;
public static IRepository<Author> _authors; public static IRepository<Author> _authors;
public static IRepository<Genre> _genres; public static IRepository<Genre> _genres;
public static IRepository<Entities.Tag> _tags;
public static IRepository<DBCacheRecord> _cache; public static IRepository<DBCacheRecord> _cache;
public static IRepository<Member> _members; public static IRepository<Member> _members;
private static IRepository<BookNote> _bookNotesRepository; private static IRepository<BookNote> _bookNotesRepository;
@ -33,13 +32,8 @@ namespace BukiVedi.Shared.Services
_books = new MongoRepository<Book>(_client, DBName, "books"); _books = new MongoRepository<Book>(_client, DBName, "books");
_authors = new MongoRepository<Author>(_client, DBName, "authors"); _authors = new MongoRepository<Author>(_client, DBName, "authors");
_genres = new MongoRepository<Genre>(_client, DBName, "genres"); _genres = new MongoRepository<Genre>(_client, DBName, "genres");
_tags = new MongoRepository<Entities.Tag>(_client, DBName, "tags");
_cache = new MongoRepository<DBCacheRecord>(_client, DBName, "cache"); _cache = new MongoRepository<DBCacheRecord>(_client, DBName, "cache");
_members = new MongoRepository<Member>(_client, DBName, "Accounts"); _members = new MongoRepository<Member>(_client, DBName, "Accounts");
CreateCacheIndex();
CreateBookIndex();
CreateAuthorIndex();
CreateTagIndex();
_bookNotesRepository = new MongoRepository<BookNote>(_client, DBName, "bookNotes"); _bookNotesRepository = new MongoRepository<BookNote>(_client, DBName, "bookNotes");
_disgustingAuthorsRepository = new MongoRepository<DisgustingAuthor>(_client, DBName, "disgustingAuthors"); _disgustingAuthorsRepository = new MongoRepository<DisgustingAuthor>(_client, DBName, "disgustingAuthors");
@ -48,11 +42,15 @@ namespace BukiVedi.Shared.Services
_favoriteBooksRepository = new MongoRepository<FavoriteBook>(_client, DBName, "favoriteBooks"); _favoriteBooksRepository = new MongoRepository<FavoriteBook>(_client, DBName, "favoriteBooks");
_readQueueReporitory = new MongoRepository<ReadQueueItem>(_client, DBName, "readQueue"); _readQueueReporitory = new MongoRepository<ReadQueueItem>(_client, DBName, "readQueue");
_userTagRepository = new MongoRepository<UserTag>(_client, DBName, "userTags"); _userTagRepository = new MongoRepository<UserTag>(_client, DBName, "userTags");
CreateCacheIndex();
CreateBookIndex();
CreateAuthorIndex();
CreateTagIndex();
} }
public static IRepository<Book> Books => _books; public static IRepository<Book> Books => _books;
public static IRepository<Author> Authors => _authors; public static IRepository<Author> Authors => _authors;
public static IRepository<Genre> Genres => _genres; public static IRepository<Genre> Genres => _genres;
public static IRepository<Entities.Tag> Tags => _tags;
public static IRepository<DBCacheRecord> Cache => _cache; public static IRepository<DBCacheRecord> Cache => _cache;
public static IRepository<Member> Members => _members; public static IRepository<Member> Members => _members;
@ -110,10 +108,12 @@ namespace BukiVedi.Shared.Services
private static void CreateTagIndex() private static void CreateTagIndex()
{ {
var options = new CreateIndexOptions { DefaultLanguage = "russian", Name = "idx_tag_name" }; {
var indexModel = new CreateIndexModel<Entities.Tag>(Builders<Entities.Tag>.IndexKeys.Text(x => x.Name), options); var entityIndexOption = new CreateIndexOptions { Name = "idx_tag_user", };
Tags.Collection.Indexes.CreateOne(indexModel); var entityIndexModel = new CreateIndexModel<UserTag>(Builders<UserTag>.IndexKeys.Ascending(f => f.UserId), entityIndexOption);
Log.Info($"[Tables.CreateTagIndex] Tag name FTS index created"); UserTag.Collection.Indexes.CreateOne(entityIndexModel);
Log.Info($"[Tables.CreateBookIndex] UserTag.UserId index created");
}
} }
} }
} }

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

@ -1 +1 @@
a43e071fcbccab0ead5e03567912c2800cfe653f607dc22a76bee59d3a550861 2dd5b54c18e88209da1a71d5242ff522bc0fd3a0e6546e22e8f2e147cbf052ea

@ -1 +1 @@
c246cb9bf18ceea2b0b5669878b9291f51d46cfe334c35203c17b29d140d3f6e 7b3acc941dfb3fa02869b199757f63cf5c2d448be69b86d6ea4868d6b0baaeab

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

@ -1 +1 @@
653e4a45fb94a4537544a949cec4dcc2f65aef478456fc0ccaf0293cf0578f31 fe3e0e62e5f77e029faed2f91070935d4c3a0d0cb1db79d7ecaff8cedab2dd72

@ -1 +1 @@
ec5d55505af05defa41720e2c3d4601434ddea2f1a5d082379bc4eaf9e50c2f7 278f64daa96004e2c73878c12244621a31aa6900464180cb740071bee2f71dcb

@ -1,6 +1,7 @@
using BukiVedi.Shared.Services; using BukiVedi.Shared.Services;
using FB2Library; using FB2Library;
using System.Text; using System.Text;
using ZeroLevel;
namespace TitleReader namespace TitleReader
{ {
@ -18,6 +19,10 @@ namespace TitleReader
var library = new Library(); var library = new Library();
//await Tables.UserTag.Write(new BukiVedi.Shared.Entities.UserTag { UserId = "660866a1f944622b13b72017", BookId = "660587c9481e83af64cce15e", Name = "шиза" });
//await Tables.UserTag.Write(new BukiVedi.Shared.Entities.UserTag { UserId = "660866a1f944622b13b72017", BookId = "6605680a481e83af64c3a7d4", Name = "перечитывать" });
//await Tables.UserTag.Write(new BukiVedi.Shared.Entities.UserTag { UserId = "660866a1f944622b13b72017", BookId = "66057488481e83af64c802b8", Name = "нараз" });
/*************** RESCAN LIBRARY ***************/ /*************** RESCAN LIBRARY ***************/
// await library.Rescan(); // await library.Rescan();

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

@ -1 +1 @@
b064e79da2f4298b356e06af43b5adc09f838eadea0c95d3b75f3feb5730691d bb1821fe2cb7b9fa9228f61c79c42670de63950df37dc8a32cd1652c3c4b559c

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

@ -1 +1 @@
e29e3847e1870a8b2283d9767f0d8bba17e27ffc069e272dc56eb006e566030b 6c9817ef1ac85eab49751e60dcfba65ef39bf7879efc66ce464ceae2e337e808

Loading…
Cancel
Save

Powered by TurnKey Linux.