Rework depot results, API docs via Scalar
This commit is contained in:
parent
37ba817706
commit
ce17b7999f
12 changed files with 130 additions and 113 deletions
|
|
@ -9,6 +9,7 @@ namespace LANCommander.Launcher.Models
|
|||
public GroupBy GroupBy { get; set; } = GroupBy.None;
|
||||
public SortBy SortBy { get; set; } = SortBy.Title;
|
||||
public SortDirection SortDirection { get; set; } = SortDirection.Ascending;
|
||||
public ICollection<Collection> Collections { get; set; }
|
||||
public ICollection<Engine> Engines { get; set; }
|
||||
public ICollection<Genre> Genres { get; set; }
|
||||
public ICollection<Tag> Tags { get; set; }
|
||||
|
|
|
|||
|
|
@ -44,11 +44,11 @@ namespace LANCommander.Launcher.Services
|
|||
|
||||
using (var op = Logger.BeginOperation(LogLevel.Trace, "Loading depot items from host"))
|
||||
{
|
||||
var games = await Client.Depot.GetGamesAsync();
|
||||
var results = await Client.Depot.GetAsync();
|
||||
|
||||
Filter.Populate(games);
|
||||
Filter.Populate(results);
|
||||
|
||||
foreach (var item in games.Select(g => new ListItem(g)).OrderByTitle(g => !String.IsNullOrWhiteSpace(g.SortName) ? g.SortName : g.Name))
|
||||
foreach (var item in results.Games.Select(g => new ListItem(g)).OrderByTitle(g => !String.IsNullOrWhiteSpace(g.SortName) ? g.SortName : g.Name))
|
||||
{
|
||||
Items.Add(item);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,53 +25,21 @@ namespace LANCommander.Launcher.Models
|
|||
|
||||
public Func<ListItem, string[]> GroupSelector { get; set; } = _ => new string[] { };
|
||||
|
||||
public void Populate(IEnumerable<SDK.Models.DepotGame> games)
|
||||
public void Populate(DepotResults results)
|
||||
{
|
||||
var multiplayerModes = games.Where(g => g.MultiplayerModes != null).SelectMany(g => g.MultiplayerModes);
|
||||
var multiplayerModes = results.Games
|
||||
.Where(g => g.MultiplayerModes != null)
|
||||
.SelectMany(g => g.MultiplayerModes);
|
||||
|
||||
DataSource.Engines = games
|
||||
.Select(i => i.Engine)
|
||||
.Where(e => e != null)
|
||||
.DistinctBy(e => e.Id)
|
||||
.OrderBy(e => e.Name)
|
||||
.ToList();
|
||||
DataSource.Collections = results.Collections.OrderBy(c => c.Name).ToList();
|
||||
DataSource.Engines = results.Engines.OrderBy(e => e.Name).ToList();
|
||||
DataSource.Genres = results.Genres.OrderBy(g => g.Name).ToList();
|
||||
DataSource.Tags = results.Tags.OrderBy(t => t.Name).ToList();
|
||||
DataSource.Platforms = results.Platforms.OrderBy(p => p.Name).ToList();
|
||||
DataSource.Developers = results.Companies.OrderBy(c => c.Name).ToList();
|
||||
DataSource.Publishers = results.Companies.OrderBy(c => c.Name).ToList();
|
||||
|
||||
DataSource.Genres = games
|
||||
.SelectMany(i => i.Genres)
|
||||
.Where(g => g != null)
|
||||
.DistinctBy(g => g.Id)
|
||||
.OrderBy(g => g.Name)
|
||||
.ToList();
|
||||
|
||||
DataSource.Tags = games
|
||||
.SelectMany(i => i.Tags)
|
||||
.Where(t => t != null)
|
||||
.DistinctBy(t => t.Id)
|
||||
.OrderBy(t => t.Name)
|
||||
.ToList();
|
||||
|
||||
DataSource.Platforms = games
|
||||
.SelectMany(i => i.Platforms)
|
||||
.Where(p => p != null)
|
||||
.DistinctBy(p => p.Id)
|
||||
.OrderBy(p => p.Name)
|
||||
.ToList();
|
||||
|
||||
DataSource.Developers = games
|
||||
.SelectMany(i => i.Developers)
|
||||
.Where(c => c != null)
|
||||
.DistinctBy(c => c.Id)
|
||||
.OrderBy(c => c.Name)
|
||||
.ToList();
|
||||
|
||||
DataSource.Publishers = games
|
||||
.SelectMany(i => i.Publishers)
|
||||
.Where(c => c != null)
|
||||
.DistinctBy(c => c.Id)
|
||||
.OrderBy(c => c.Name)
|
||||
.ToList();
|
||||
|
||||
if (games.Any(li => li.Singleplayer))
|
||||
if (results.Games.Any(li => li.Singleplayer))
|
||||
DataSource.MinPlayers = 1;
|
||||
else if (multiplayerModes.Any())
|
||||
DataSource.MinPlayers = multiplayerModes.Where(i => i != null).Min(i => i.MinPlayers);
|
||||
|
|
@ -88,19 +56,25 @@ namespace LANCommander.Launcher.Models
|
|||
items = items.Where(i => i.Name?.IndexOf(SelectedOptions.Title, StringComparison.OrdinalIgnoreCase) >= 0 || i.SortName?.IndexOf(SelectedOptions.Title, StringComparison.OrdinalIgnoreCase) >= 0);
|
||||
|
||||
if (SelectedOptions.Engines != null && SelectedOptions.Engines.Any())
|
||||
items = items.Where(i => SelectedOptions.Engines.Any(e => e.Id == (i.DataItem as DepotGame)?.Engine?.Id));
|
||||
items = items.Where(i => SelectedOptions.Engines.Any(e => (i.DataItem as DepotGame).EngineId == e.Id));
|
||||
|
||||
if (SelectedOptions.Collections != null && SelectedOptions.Collections.Any())
|
||||
items = items.Where(i => SelectedOptions.Collections.Any(fc => (i.DataItem as DepotGame).Collections.Contains(fc.Id)));
|
||||
|
||||
if (SelectedOptions.Genres != null && SelectedOptions.Genres.Any())
|
||||
items = items.Where(i => SelectedOptions.Genres.Any(fg => (i.DataItem as DepotGame).Genres.Any(g => fg.Id == g.Id)));
|
||||
items = items.Where(i => SelectedOptions.Genres.Any(fg => (i.DataItem as DepotGame).Genres.Contains(fg.Id)));
|
||||
|
||||
if (SelectedOptions.Tags != null && SelectedOptions.Tags.Any())
|
||||
items = items.Where(i => SelectedOptions.Tags.Any(ft => (i.DataItem as DepotGame).Tags.Any(t => ft.Id == t.Id)));
|
||||
items = items.Where(i => SelectedOptions.Tags.Any(ft => (i.DataItem as DepotGame).Tags.Contains(ft.Id)));
|
||||
|
||||
if (SelectedOptions.Developers != null && SelectedOptions.Developers.Any())
|
||||
items = items.Where(i => SelectedOptions.Developers.Any(fc => (i.DataItem as DepotGame).Developers.Any(c => fc.Id == c.Id)));
|
||||
items = items.Where(i => SelectedOptions.Developers.Any(fc => (i.DataItem as DepotGame).Developers.Contains(fc.Id)));
|
||||
|
||||
if (SelectedOptions.Publishers != null && SelectedOptions.Publishers.Any())
|
||||
items = items.Where(i => SelectedOptions.Publishers.Any(fc => (i.DataItem as DepotGame).Publishers.Any(c => fc.Id == c.Id)));
|
||||
items = items.Where(i => SelectedOptions.Publishers.Any(fc => (i.DataItem as DepotGame).Publishers.Contains(fc.Id)));
|
||||
|
||||
if (SelectedOptions.Platforms != null && SelectedOptions.Platforms.Any())
|
||||
items = items.Where(i => SelectedOptions.Platforms.Any(fp => (i.DataItem as DepotGame).Platforms.Contains(fp.Id)));
|
||||
|
||||
if (SelectedOptions.MinPlayers != null)
|
||||
items = items.Where(i => (i.DataItem as DepotGame).MultiplayerModes.Any(mm => mm.MinPlayers <= SelectedOptions.MinPlayers && mm.MaxPlayers >= SelectedOptions.MinPlayers));
|
||||
|
|
@ -137,25 +111,25 @@ namespace LANCommander.Launcher.Models
|
|||
|
||||
case Enums.GroupBy.Collection:
|
||||
GroupSelector = (g) =>
|
||||
(g.DataItem as DepotGame)?.Collections?
|
||||
.Where(c => c?.Name != null)
|
||||
DataSource.Collections
|
||||
.Where(c => (g.DataItem as DepotGame).Collections.Contains(c.Id))
|
||||
.Select(c => c.Name)
|
||||
.ToArray() ?? Array.Empty<string>();
|
||||
break;
|
||||
|
||||
case Enums.GroupBy.Genre:
|
||||
GroupSelector = (g) =>
|
||||
(g.DataItem as DepotGame)?.Genres?
|
||||
.Where(ge => ge?.Name != null)
|
||||
.Select(ge => ge.Name)
|
||||
DataSource.Genres
|
||||
.Where(ge => (g.DataItem as DepotGame).Genres.Contains(ge.Id))
|
||||
.Select(g => g.Name)
|
||||
.ToArray() ?? Array.Empty<string>();
|
||||
break;
|
||||
|
||||
case Enums.GroupBy.Platform:
|
||||
GroupSelector = (g) =>
|
||||
(g.DataItem as DepotGame)?.Platforms?
|
||||
.Where(p => p?.Name != null)
|
||||
.Select(p => p.Name)
|
||||
DataSource.Platforms
|
||||
.Where(p => (g.DataItem as DepotGame).Platforms.Contains(p.Id))
|
||||
.Select(g => g.Name)
|
||||
.ToArray() ?? Array.Empty<string>();
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,6 +33,9 @@
|
|||
<FormItem Label="Engine">
|
||||
<TagsInput Entities="context.DataSource.Engines" @bind-Values="@context.SelectedOptions.Engines" OptionLabelSelector="e => e.Name" TItem="Engine" />
|
||||
</FormItem>
|
||||
<FormItem Label="Collection">
|
||||
<TagsInput Entities="context.DataSource.Collections" @bind-Values="@context.SelectedOptions.Collections" OptionLabelSelector="c => c.Name" TItem="Collection" />
|
||||
</FormItem>
|
||||
<FormItem Label="Genre">
|
||||
<TagsInput Entities="context.DataSource.Genres" @bind-Values="@context.SelectedOptions.Genres" OptionLabelSelector="g => g.Name" TItem="Genre" />
|
||||
</FormItem>
|
||||
|
|
|
|||
|
|
@ -21,13 +21,13 @@ namespace LANCommander.SDK.Models
|
|||
public bool InLibrary { get; set; }
|
||||
public GameType Type { get; set; }
|
||||
public Media Cover { get; set; }
|
||||
public IEnumerable<Collection> Collections { get; set; }
|
||||
public IEnumerable<Company> Developers { get; set; }
|
||||
public IEnumerable<Company> Publishers { get; set; }
|
||||
public Engine Engine { get; set; }
|
||||
public IEnumerable<Genre> Genres { get; set; }
|
||||
public IEnumerable<Guid> Collections { get; set; }
|
||||
public IEnumerable<Guid> Developers { get; set; }
|
||||
public IEnumerable<Guid> Publishers { get; set; }
|
||||
public Guid EngineId { get; set; }
|
||||
public IEnumerable<Guid> Genres { get; set; }
|
||||
public IEnumerable<MultiplayerMode> MultiplayerModes { get; set; }
|
||||
public IEnumerable<Platform> Platforms { get; set; }
|
||||
public IEnumerable<Tag> Tags { get; set; }
|
||||
public IEnumerable<Guid> Platforms { get; set; }
|
||||
public IEnumerable<Guid> Tags { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
19
LANCommander.SDK/Models/DepotResults.cs
Normal file
19
LANCommander.SDK/Models/DepotResults.cs
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace LANCommander.SDK.Models
|
||||
{
|
||||
public class DepotResults
|
||||
{
|
||||
public ICollection<DepotGame> Games { get; set; }
|
||||
public ICollection<Collection> Collections { get; set; }
|
||||
public ICollection<Company> Companies { get; set; }
|
||||
public ICollection<Engine> Engines { get; set; }
|
||||
public ICollection<Genre> Genres { get; set; }
|
||||
public ICollection<Platform> Platforms { get; set; }
|
||||
public ICollection<Tag> Tags { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -27,9 +27,9 @@ namespace LANCommander.SDK.Services
|
|||
Logger = logger;
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<DepotGame>> GetGamesAsync()
|
||||
public async Task<DepotResults> GetAsync()
|
||||
{
|
||||
return await Client.GetRequestAsync<IEnumerable<DepotGame>>("/api/Depot/Games");
|
||||
return await Client.GetRequestAsync<DepotResults>("/api/Depot");
|
||||
}
|
||||
|
||||
public async Task<DepotGame> GetGameAsync(Guid gameId)
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ namespace LANCommander.Server.Services
|
|||
|
||||
public async Task<Library> GetByUserIdAsync(Guid userId)
|
||||
{
|
||||
var library = await Include(l => l.Games.Select(g => g.Id)).FirstOrDefaultAsync(l => l.User.Id == userId);
|
||||
var library = await Include(l => l.Games).FirstOrDefaultAsync(l => l.User.Id == userId);
|
||||
|
||||
if (library == null)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -49,7 +49,25 @@ namespace LANCommander.Server
|
|||
CreateMap<Data.Models.Game, SDK.Models.DepotGame>()
|
||||
.ForMember(dest =>
|
||||
dest.Cover,
|
||||
opt => opt.MapFrom(src => src.Media.Where(m => m.Type == SDK.Enums.MediaType.Cover).FirstOrDefault()));
|
||||
opt => opt.MapFrom(src => src.Media.Where(m => m.Type == SDK.Enums.MediaType.Cover).FirstOrDefault()))
|
||||
.ForMember(dest =>
|
||||
dest.Collections,
|
||||
opt => opt.MapFrom(src => src.Tags.Select(c => c.Id)))
|
||||
.ForMember(dest =>
|
||||
dest.Developers,
|
||||
opt => opt.MapFrom(src => src.Developers.Select(c => c.Id)))
|
||||
.ForMember(dest =>
|
||||
dest.Publishers,
|
||||
opt => opt.MapFrom(src => src.Publishers.Select(c => c.Id)))
|
||||
.ForMember(dest =>
|
||||
dest.Genres,
|
||||
opt => opt.MapFrom(src => src.Genres.Select(g => g.Id)))
|
||||
.ForMember(dest =>
|
||||
dest.Platforms,
|
||||
opt => opt.MapFrom(src => src.Platforms.Select(p => p.Id)))
|
||||
.ForMember(dest =>
|
||||
dest.Tags,
|
||||
opt => opt.MapFrom(src => src.Tags.Select(t => t.Id)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,69 +20,66 @@ namespace LANCommander.Server.Controllers.Api
|
|||
private readonly IMapper Mapper;
|
||||
private readonly IFusionCache Cache;
|
||||
private readonly GameService GameService;
|
||||
private readonly CollectionService CollectionService;
|
||||
private readonly CompanyService CompanyService;
|
||||
private readonly EngineService EngineService;
|
||||
private readonly GenreService GenreService;
|
||||
private readonly PlatformService PlatformService;
|
||||
private readonly TagService TagService;
|
||||
private readonly LibraryService LibraryService;
|
||||
private readonly UserService UserService;
|
||||
private readonly DatabaseContext DatabaseContext;
|
||||
|
||||
public DepotController(
|
||||
ILogger<DepotController> logger,
|
||||
IMapper mapper,
|
||||
IFusionCache cache,
|
||||
GameService gameService,
|
||||
CollectionService collectionService,
|
||||
CompanyService companyService,
|
||||
EngineService engineService,
|
||||
GenreService genreService,
|
||||
PlatformService platformService,
|
||||
TagService tagService,
|
||||
LibraryService libraryService,
|
||||
UserService userService) : base(logger)
|
||||
UserService userService,
|
||||
DatabaseContext databaseContext) : base(logger)
|
||||
{
|
||||
Mapper = mapper;
|
||||
Cache = cache;
|
||||
GameService = gameService;
|
||||
CollectionService = collectionService;
|
||||
CompanyService = companyService;
|
||||
EngineService = engineService;
|
||||
GenreService = genreService;
|
||||
PlatformService = platformService;
|
||||
TagService = tagService;
|
||||
LibraryService = libraryService;
|
||||
UserService = userService;
|
||||
DatabaseContext = databaseContext;
|
||||
}
|
||||
|
||||
[HttpGet("Games")]
|
||||
public async Task<IEnumerable<SDK.Models.DepotGame>> GetGamesAsync()
|
||||
[HttpGet]
|
||||
public async Task<SDK.Models.DepotResults> GetAsync()
|
||||
{
|
||||
var user = await UserService.GetAsync(User?.Identity?.Name);
|
||||
var library = await LibraryService.GetByUserIdAsync(user.Id);
|
||||
|
||||
var libraryGameIds = library.Games.Where(g => g != null).Select(g => g.Id).ToList();
|
||||
|
||||
var games = await Cache.GetOrSetAsync("DepotGames", async _ =>
|
||||
var results = await Cache.GetOrSetAsync("DepotResults", async _ =>
|
||||
{
|
||||
return await GameService
|
||||
.Include(g => g.Media.Where(m => m.Type == SDK.Enums.MediaType.Cover))
|
||||
.Include(g => g.Collections.Select(c => c.Id))
|
||||
.Include(g => g.Developers.Select(c => c.Id))
|
||||
.Include(g => g.Genres.Select(g => g.Id))
|
||||
.Include(g => g.MultiplayerModes)
|
||||
.Include(g => g.Platforms.Select(p => p.Id))
|
||||
.Include(g => g.Publishers.Select(c => c.Id))
|
||||
.Include(g => g.Tags.Select(t => t.Id))
|
||||
.GetAsync<SDK.Models.DepotGame>();
|
||||
}, TimeSpan.MaxValue);
|
||||
|
||||
var accessibleGames = games.ToList();
|
||||
|
||||
if (Settings.Roles.RestrictGamesByCollection && !User.IsInRole(RoleService.AdministratorRoleName))
|
||||
{
|
||||
var roles = await UserService.GetRolesAsync(User?.Identity.Name);
|
||||
|
||||
var accessibleCollectionIds = roles.SelectMany(r => r.Collections.Select(c => c.Id)).Distinct();
|
||||
|
||||
accessibleGames = games.Where(g => g.Collections.Any(c => accessibleCollectionIds.Contains(c.Id))).ToList();
|
||||
|
||||
foreach (var game in accessibleGames)
|
||||
return new SDK.Models.DepotResults
|
||||
{
|
||||
game.Collections = game.Collections.Where(c => accessibleCollectionIds.Contains(c.Id));
|
||||
}
|
||||
}
|
||||
Games = await GameService.GetAsync<DepotGame>(),
|
||||
Collections = await CollectionService.GetAsync<SDK.Models.Collection>(),
|
||||
Companies = await CompanyService.GetAsync<SDK.Models.Company>(),
|
||||
Engines = await EngineService.GetAsync<SDK.Models.Engine>(),
|
||||
Genres = await GenreService.GetAsync<SDK.Models.Genre>(),
|
||||
Platforms = await PlatformService.GetAsync<SDK.Models.Platform>(),
|
||||
Tags = await TagService.GetAsync<SDK.Models.Tag>(),
|
||||
};
|
||||
});
|
||||
|
||||
foreach (var game in accessibleGames)
|
||||
{
|
||||
if (libraryGameIds.Contains(game.Id))
|
||||
game.InLibrary = true;
|
||||
}
|
||||
|
||||
return accessibleGames;
|
||||
return results;
|
||||
}
|
||||
|
||||
[HttpGet("Games/{id}")]
|
||||
|
|
|
|||
|
|
@ -106,6 +106,7 @@
|
|||
<PackageReference Include="Razor.Templating.Core" Version="2.0.0" />
|
||||
<PackageReference Include="RegParserDotNet" Version="1.1.1" />
|
||||
<PackageReference Include="rix0rrr.BeaconLib" Version="1.0.2" />
|
||||
<PackageReference Include="Scalar.AspNetCore" Version="1.2.56" />
|
||||
<PackageReference Include="Semver" Version="2.3.0" />
|
||||
<PackageReference Include="Serilog" Version="4.0.2" />
|
||||
<PackageReference Include="Serilog.AspNetCore" Version="8.0.3" />
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ using LANCommander.Server.Jobs.Background;
|
|||
using Microsoft.Data.Sqlite;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Microsoft.CodeAnalysis.Options;
|
||||
using Scalar.AspNetCore;
|
||||
|
||||
namespace LANCommander.Server
|
||||
{
|
||||
|
|
@ -234,7 +235,7 @@ namespace LANCommander.Server
|
|||
builder.Services.AddSwaggerGen(options =>
|
||||
{
|
||||
options.CustomSchemaIds(type => type.ToString());
|
||||
options.AddSecurityDefinition("Bearer", new Microsoft.OpenApi.Models.OpenApiSecurityScheme
|
||||
options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
|
||||
{
|
||||
In = ParameterLocation.Header,
|
||||
Description = "Enter a valid access token",
|
||||
|
|
@ -363,8 +364,11 @@ namespace LANCommander.Server
|
|||
app.UseHsts();
|
||||
}
|
||||
|
||||
app.UseSwagger();
|
||||
app.UseSwaggerUI();
|
||||
app.UseSwagger(options =>
|
||||
{
|
||||
options.RouteTemplate = "/openapi/{documentName}.json";
|
||||
});
|
||||
app.MapScalarApiReference();
|
||||
app.UseHangfireDashboard();
|
||||
|
||||
// app.UseHttpsRedirection();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue