LANCommander/LANCommander.Server.Services/Providers/Metadata/IgdbMetadataProvider.cs
2026-06-04 01:29:31 -05:00

141 lines
No EOL
5 KiB
C#

using System.Text;
using IGDB;
using LANCommander.SDK.Models.Manifest;
using Microsoft.Extensions.Logging;
namespace LANCommander.Server.Services.Providers.Metadata;
public class IgdbMetadataProvider(
SettingsProvider<Settings.Settings> settingsProvider,
ILogger<IgdbMetadataProvider> logger) : IMetadataProvider
{
private IGDBClient? _client;
private const string DefaultFields = "*";
private void Authenticate()
{
if (_client is not null)
return;
var clientId = settingsProvider.CurrentValue.Server.IGDB.ClientId;
var clientSecret = settingsProvider.CurrentValue.Server.IGDB.ClientSecret;
// Client will throw exceptions if no credentials are configured
_client = new IGDBClient(clientId, clientSecret);
}
public string ProviderName => "IGDB";
public bool IsAvailable => !string.IsNullOrWhiteSpace(settingsProvider.CurrentValue.Server.IGDB.ClientId)
&& !string.IsNullOrWhiteSpace(settingsProvider.CurrentValue.Server.IGDB.ClientSecret);
public async Task<MetadataSearchResultsCollection<Game>?> SearchGamesAsync(string input, int limit = 10, int offset = 0)
{
Authenticate();
var fields = DefaultFields.Split(',').ToList();
fields.Add("involved_companies.developer");
fields.Add("involved_companies.publisher");
fields.Add("involved_companies.company.name");
fields.Add("platforms.*");
var sb = new StringBuilder();
sb.Append($"search \"{input}\";");
sb.Append($"fields {String.Join(',', fields)};");
sb.Append($"limit {limit};");
sb.Append($"offset {offset};");
var results = await _client!.QueryAsync<IGDB.Models.Game>(IGDBClient.Endpoints.Games, sb.ToString());
return new MetadataSearchResultsCollection<Game>(results
.Where(g => g is not null && g.Id is not null)
.Select(g => new MetadataSearchResult<Game>(g?.Id?.ToString() ?? string.Empty, ConvertGame(g))).ToList(),
results.Length == limit);
}
public async Task<Game?> GetGameAsync(string gameId)
{
var fields = DefaultFields.Split(',').ToList();
fields.Add("genres.*");
fields.Add("game_modes.*");
fields.Add("multiplayer_modes.*");
fields.Add("release_dates.*");
fields.Add("platforms.*");
fields.Add("keywords.*");
fields.Add("involved_companies.developer");
fields.Add("involved_companies.publisher");
fields.Add("involved_companies.company.name");
fields.Add("cover.*");
fields.Add("game_engines.*");
var games = await _client.QueryAsync<IGDB.Models.Game>(IGDBClient.Endpoints.Games, $"fields {String.Join(',', fields)}; where id = {gameId};");
if (games is null)
return null;
return ConvertGame(games.FirstOrDefault());
}
private Game ConvertGame(IGDB.Models.Game? igdbGame)
{
var game = new Game
{
Title = igdbGame.Name,
Description = igdbGame.Summary,
ReleasedOn = igdbGame.FirstReleaseDate.GetValueOrDefault().UtcDateTime,
ExternalIds = new List<GameExternalId>
{
new GameExternalId { Provider = "IGDB", ExternalId = igdbGame.Id?.ToString() ?? string.Empty }
},
};
if (igdbGame.GameModes?.Values?.Any() ?? false)
game.Singleplayer = igdbGame.GameModes.Values.Any(gm => gm.Name == "Single player");
if (igdbGame.InvolvedCompanies?.Values?.Any() ?? false)
{
game.Developers = igdbGame.InvolvedCompanies.Values
.Where(c => c.Developer.GetValueOrDefault())
.Select(c => new Company { Name = c.Company?.Value?.Name })
.ToList();
game.Publishers = igdbGame.InvolvedCompanies.Values
.Where(c => c.Publisher.GetValueOrDefault())
.Select(c => new Company { Name = c.Company?.Value?.Name })
.ToList();
}
if (igdbGame.GameEngines?.Values?.Any() ?? false)
{
game.Engine = new Engine
{
Name = igdbGame.GameEngines.Values.FirstOrDefault()?.Name ?? string.Empty
};
}
if (igdbGame.Platforms?.Values?.Any() ?? false)
{
game.Platforms = igdbGame.Platforms.Values
.Select(p => new Platform { Name = p.Name })
.ToList();
}
if (igdbGame.Genres?.Values?.Any() ?? false)
{
game.Genres = igdbGame.Genres.Values
.Select(g => new Genre { Name = g.Name })
.ToList();
}
if (igdbGame.Keywords?.Values?.Any() ?? false)
{
game.Tags = igdbGame.Keywords.Values
.Select(k => new Tag { Name = k.Name })
.ToList();
}
return game;
}
}