LANCommander/LANCommander.Server.ImportExport/Importers/GameImporter.cs

210 lines
7 KiB
C#

using LANCommander.SDK.Enums;
using LANCommander.SDK.Models.Manifest;
using LANCommander.Server.ImportExport.Models;
using LANCommander.Server.Services;
using Microsoft.Extensions.Logging;
namespace LANCommander.Server.ImportExport.Importers;
public class GameImporter(
ILogger<GameImporter> logger,
GameService gameService,
RedistributableService redistributableService,
UserService userService) : BaseImporter<Game>
{
public override string GetKey(Game record)
=> $"{nameof(Game)}/{record.Id}";
public override async Task<ImportItemInfo<Game>> GetImportInfoAsync(Game record)
{
return new ImportItemInfo<Game>
{
Type = ImportExportRecordType.Game,
Name = record.Title,
Record = record,
};
}
public override async Task<bool> CanImportAsync(Game record) => true;
public override async Task<bool> AddAsync(Game record)
{
var game = new Data.Models.Game
{
Id = record.Id,
Title = record.Title,
SortTitle = record.SortTitle,
Description = record.Description,
Notes = record.Notes,
ReleasedOn = record.ReleasedOn,
Singleplayer = record.Singleplayer,
Type = record.Type,
ExternalIds = record.ExternalIds?.Select(e => new Data.Models.GameExternalId
{
Provider = e.Provider,
ExternalId = e.ExternalId,
}).ToList(),
CreatedOn = record.CreatedOn,
UpdatedOn = record.UpdatedOn,
DirectoryName = record.DirectoryName,
};
if (!String.IsNullOrWhiteSpace(record.CreatedBy))
game.CreatedBy = await userService.GetAsync(record.CreatedBy);
if (!String.IsNullOrWhiteSpace(record.UpdatedBy))
game.UpdatedBy = await userService.GetAsync(record.UpdatedBy);
try
{
await gameService.AddAsync(game);
await UpdateRelationshipsAsync();
return true;
}
catch (Exception ex)
{
logger.LogError(ex, "Could not add game | {Key}", GetKey(record));
return false;
}
}
public override async Task<bool> UpdateAsync(Game record)
{
var existing = await gameService.FirstOrDefaultAsync(g => g.Id == record.Id || g.Title == record.Title);
try
{
existing.Title = record.Title;
existing.SortTitle = record.SortTitle;
existing.Description = record.Description;
existing.Notes = record.Notes;
existing.ReleasedOn = record.ReleasedOn;
existing.Singleplayer = record.Singleplayer;
existing.Type = record.Type;
existing.ExternalIds = record.ExternalIds?.Select(e => new Data.Models.GameExternalId
{
Provider = e.Provider,
ExternalId = e.ExternalId,
}).ToList();
existing.CreatedOn = record.CreatedOn;
existing.DirectoryName = record.DirectoryName;
if (!String.IsNullOrWhiteSpace(record.CreatedBy))
existing.CreatedBy = await userService.GetAsync(record.CreatedBy);
if (!String.IsNullOrWhiteSpace(record.UpdatedBy))
existing.UpdatedBy = await userService.GetAsync(record.UpdatedBy);
await gameService.UpdateAsync(existing);
await UpdateRelationshipsAsync();
return true;
}
catch (Exception ex)
{
logger.LogError(ex, "Could not update game | {Key}", GetKey(record));
return false;
}
}
public override async Task<bool> IngestAsync(IImportAsset asset)
{
throw new NotImplementedException();
}
public override async Task<bool> ExistsAsync(Game record)
{
return await gameService.ExistsAsync(g => g.Id == record.Id || g.Title == record.Title);
}
public async Task UpdateRelationshipsAsync()
{
if (ImportContext.Manifest is not Game)
return;
var manifest = ImportContext.Manifest as Game;
if (manifest == null)
return;
var game = await gameService
.GetAsync(manifest.Id);
await gameService.SyncRelatedCollectionAsync(
game,
g => g.Collections,
manifest.Collections,
r => c => c.Name == r.Name);
await gameService.SyncRelatedCollectionAsync(
game,
g => g.Developers,
manifest.Developers,
r => c => c.Name == r.Name);
await gameService.SyncRelatedCollectionAsync(
game,
g => g.Genres,
manifest.Genres,
r => g => g.Name == r.Name);
await gameService.SyncRelatedCollectionAsync(
game,
g => g.Platforms,
manifest.Platforms,
r => p => p.Name == r.Name);
await gameService.SyncRelatedCollectionAsync(
game,
g => g.Publishers,
manifest.Publishers,
r => p => p.Name == r.Name);
await gameService.SyncRelatedCollectionAsync(
game,
g => g.Tags,
manifest.Tags,
r => t => t.Name == r.Name);
if (manifest.Redistributables != null && manifest.Redistributables.Any())
{
await gameService.SyncRelatedCollectionAsync(
game,
g => g.Redistributables,
manifest.Redistributables,
r => rd => rd.Id == r.Id || rd.Name == r.Name);
foreach (var redistributable in manifest.Redistributables)
{
if (redistributable.Options != null && redistributable.Options.Any())
{
var existing = await redistributableService.FirstOrDefaultAsync(r => r.Id == redistributable.Id || r.Name == redistributable.Name);
if (existing != null)
{
var optionsJson = System.Text.Json.JsonSerializer.Serialize(redistributable.Options);
await gameService.SetRedistributableOptionsAsync(game.Id, existing.Id, optionsJson);
}
}
}
}
if (!string.IsNullOrWhiteSpace(manifest.BaseGame) || manifest.BaseGameId != Guid.Empty)
{
Data.Models.Game? baseGame = null;
if (manifest.BaseGameId != Guid.Empty)
baseGame = await gameService.FirstOrDefaultAsync(g => g.Id == manifest.BaseGameId);
if (baseGame == null && !String.IsNullOrWhiteSpace(manifest.BaseGame))
baseGame = await gameService.FirstOrDefaultAsync(g => g.Title == manifest.BaseGame);
if (baseGame != null && game.BaseGameId != baseGame.Id)
{
game.BaseGameId = baseGame.Id;
await gameService.UpdateAsync(game);
}
}
}
}