diff --git a/Jellyfin.Plugin.Vgmdb.csproj b/Jellyfin.Plugin.Vgmdb.csproj
deleted file mode 100644
index f78d0c8..0000000
--- a/Jellyfin.Plugin.Vgmdb.csproj
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
- net5.0
- 1.2.0.0
-
-
-
-
-
-
-
-
diff --git a/Jellyfin.Plugin.Vgmdb.sln b/Jellyfin.Plugin.Vgmdb.sln
new file mode 100644
index 0000000..7b974c5
--- /dev/null
+++ b/Jellyfin.Plugin.Vgmdb.sln
@@ -0,0 +1,16 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jellyfin.Plugin.Vgmdb", "Jellyfin.Plugin.Vgmdb\Jellyfin.Plugin.Vgmdb.csproj", "{AEE55B5F-1B35-4155-AFBF-D7586DC39F04}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {AEE55B5F-1B35-4155-AFBF-D7586DC39F04}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {AEE55B5F-1B35-4155-AFBF-D7586DC39F04}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {AEE55B5F-1B35-4155-AFBF-D7586DC39F04}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {AEE55B5F-1B35-4155-AFBF-D7586DC39F04}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+EndGlobal
diff --git a/Jellyfin.Plugin.Vgmdb/ExternalIds/VgmdbAlbumExternalId.cs b/Jellyfin.Plugin.Vgmdb/ExternalIds/VgmdbAlbumExternalId.cs
new file mode 100644
index 0000000..e4c7cde
--- /dev/null
+++ b/Jellyfin.Plugin.Vgmdb/ExternalIds/VgmdbAlbumExternalId.cs
@@ -0,0 +1,23 @@
+using MediaBrowser.Controller.Entities.Audio;
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Providers;
+
+namespace Jellyfin.Plugin.Vgmdb.ExternalIds;
+
+///
+// ReSharper disable once ClassNeverInstantiated.Global
+public class VgmdbAlbumExternalId : IExternalId
+{
+ public const string ExternalId = "VGMdbAlbum";
+
+ public string ProviderName => "VGMdb Album";
+
+ public string Key => ExternalId;
+
+ public ExternalIdMediaType? Type => ExternalIdMediaType.Album;
+
+ public string UrlFormatString => "https://vgmdb.net/album/{0}";
+
+ public bool Supports(IHasProviderIds item) => item is MusicAlbum;
+}
diff --git a/Jellyfin.Plugin.Vgmdb/ExternalIds/VgmdbArtistExternalId.cs b/Jellyfin.Plugin.Vgmdb/ExternalIds/VgmdbArtistExternalId.cs
new file mode 100644
index 0000000..2798d25
--- /dev/null
+++ b/Jellyfin.Plugin.Vgmdb/ExternalIds/VgmdbArtistExternalId.cs
@@ -0,0 +1,23 @@
+using MediaBrowser.Controller.Entities.Audio;
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Providers;
+
+namespace Jellyfin.Plugin.Vgmdb.ExternalIds;
+
+///
+// ReSharper disable once ClassNeverInstantiated.Global
+public class VgmdbArtistExternalId : IExternalId
+{
+ public const string ExternalId = "VGMdbArtist";
+
+ public string ProviderName => "VGMdb Artist";
+
+ public string Key => ExternalId;
+
+ public ExternalIdMediaType? Type => ExternalIdMediaType.Album;
+
+ public string UrlFormatString => "https://vgmdb.net/artist/{0}";
+
+ public bool Supports(IHasProviderIds item) => item is MusicArtist;
+}
diff --git a/Jellyfin.Plugin.Vgmdb/Jellyfin.Plugin.Vgmdb.csproj b/Jellyfin.Plugin.Vgmdb/Jellyfin.Plugin.Vgmdb.csproj
new file mode 100644
index 0000000..9a138f5
--- /dev/null
+++ b/Jellyfin.Plugin.Vgmdb/Jellyfin.Plugin.Vgmdb.csproj
@@ -0,0 +1,20 @@
+
+
+ net6.0
+ 1.0.0.0
+ false
+ false
+ disable
+ AllEnabledByDefault
+ ../jellyfin.ruleset
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Jellyfin.Plugin.Vgmdb/Models/AlbumResponse.cs b/Jellyfin.Plugin.Vgmdb/Models/AlbumResponse.cs
new file mode 100644
index 0000000..c22ff2d
--- /dev/null
+++ b/Jellyfin.Plugin.Vgmdb/Models/AlbumResponse.cs
@@ -0,0 +1,38 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Text.Json.Serialization;
+
+namespace Jellyfin.Plugin.Vgmdb.Models;
+
+public class AlbumResponse
+{
+ [JsonPropertyName("names")]
+ public LocalizedString Names { get; set; }
+
+ [JsonPropertyName("picture_full")]
+ public string PictureFull { get; set; }
+
+ [JsonPropertyName("picture_small")]
+ public string PictureSmall { get; set; }
+
+ [JsonPropertyName("picture_thumb")]
+ public string PictureThumb { get; set; }
+
+ [JsonPropertyName("link")]
+ public string Link { get; set; }
+
+ [JsonPropertyName("notes")]
+ public string Notes { get; set; }
+
+ [JsonPropertyName("release_date")]
+ public string ReleaseDate { get; set; }
+
+ [JsonPropertyName("categories")]
+ public IReadOnlyList Categories { get; set; } = Array.Empty();
+
+ [JsonPropertyName("organizations")]
+ public IReadOnlyList Organizations { get; set; } = Array.Empty();
+
+ public int Id => int.Parse(Link.Replace("album/", string.Empty, StringComparison.OrdinalIgnoreCase), CultureInfo.InvariantCulture);
+}
diff --git a/Jellyfin.Plugin.Vgmdb/Models/ArtistResponse.cs b/Jellyfin.Plugin.Vgmdb/Models/ArtistResponse.cs
new file mode 100644
index 0000000..6e130df
--- /dev/null
+++ b/Jellyfin.Plugin.Vgmdb/Models/ArtistResponse.cs
@@ -0,0 +1,25 @@
+using System;
+using System.Globalization;
+using System.Text.Json.Serialization;
+
+namespace Jellyfin.Plugin.Vgmdb.Models;
+
+public class ArtistResponse
+{
+ [JsonPropertyName("name")]
+ public string Name { get; set; }
+
+ [JsonPropertyName("picture_full")]
+ public string PictureFull { get; set; }
+
+ [JsonPropertyName("picture_small")]
+ public string PictureSmall { get; set; }
+
+ [JsonPropertyName("link")]
+ public string Link { get; set; }
+
+ [JsonPropertyName("notes")]
+ public string Notes { get; set; }
+
+ public int Id => int.Parse(Link.Replace("artist/", string.Empty, StringComparison.OrdinalIgnoreCase), CultureInfo.InvariantCulture);
+}
diff --git a/Jellyfin.Plugin.Vgmdb/Models/LocalizedString.cs b/Jellyfin.Plugin.Vgmdb/Models/LocalizedString.cs
new file mode 100644
index 0000000..d7107ab
--- /dev/null
+++ b/Jellyfin.Plugin.Vgmdb/Models/LocalizedString.cs
@@ -0,0 +1,20 @@
+using System.Text.Json.Serialization;
+
+namespace Jellyfin.Plugin.Vgmdb.Models;
+
+public class LocalizedString
+{
+ [JsonPropertyName("en")]
+ public string En { get; set; }
+
+ [JsonPropertyName("ja")]
+ public string Ja { get; set; }
+
+ [JsonPropertyName("jaLatn")]
+ public string JaLatn { get; set; }
+
+ public string GetPreferred()
+ {
+ return JaLatn ?? En ?? Ja;
+ }
+}
diff --git a/Jellyfin.Plugin.Vgmdb/Models/Organization.cs b/Jellyfin.Plugin.Vgmdb/Models/Organization.cs
new file mode 100644
index 0000000..28f9b77
--- /dev/null
+++ b/Jellyfin.Plugin.Vgmdb/Models/Organization.cs
@@ -0,0 +1,19 @@
+using System;
+using System.Globalization;
+using System.Text.Json.Serialization;
+
+namespace Jellyfin.Plugin.Vgmdb.Models;
+
+public class Organization
+{
+ [JsonPropertyName("link")]
+ public string Link { get; set; }
+
+ [JsonPropertyName("names")]
+ public LocalizedString Names { get; set; }
+
+ [JsonPropertyName("role")]
+ public string Role { get; set; }
+
+ public int Id => int.Parse(Link.Replace("org/", string.Empty, StringComparison.OrdinalIgnoreCase), CultureInfo.InvariantCulture);
+}
diff --git a/Jellyfin.Plugin.Vgmdb/Models/SearchResponse.cs b/Jellyfin.Plugin.Vgmdb/Models/SearchResponse.cs
new file mode 100644
index 0000000..f439ac4
--- /dev/null
+++ b/Jellyfin.Plugin.Vgmdb/Models/SearchResponse.cs
@@ -0,0 +1,9 @@
+using System.Text.Json.Serialization;
+
+namespace Jellyfin.Plugin.Vgmdb.Models;
+
+public class SearchResponse
+{
+ [JsonPropertyName("results")]
+ public SearchResponseResults Results { get; set; }
+}
diff --git a/Jellyfin.Plugin.Vgmdb/Models/SearchResponseResults.cs b/Jellyfin.Plugin.Vgmdb/Models/SearchResponseResults.cs
new file mode 100644
index 0000000..6a936cf
--- /dev/null
+++ b/Jellyfin.Plugin.Vgmdb/Models/SearchResponseResults.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Text.Json.Serialization;
+
+namespace Jellyfin.Plugin.Vgmdb.Models;
+
+public class SearchResponseResults
+{
+ [JsonPropertyName("albums")]
+ public IReadOnlyList Albums { get; set; } = Array.Empty();
+
+ [JsonPropertyName("artists")]
+ public IReadOnlyList Artists { get; set; } = Array.Empty();
+}
diff --git a/Jellyfin.Plugin.Vgmdb/Models/SearchResponseResultsAlbum.cs b/Jellyfin.Plugin.Vgmdb/Models/SearchResponseResultsAlbum.cs
new file mode 100644
index 0000000..36ead58
--- /dev/null
+++ b/Jellyfin.Plugin.Vgmdb/Models/SearchResponseResultsAlbum.cs
@@ -0,0 +1,22 @@
+using System;
+using System.Globalization;
+using System.Text.Json.Serialization;
+
+namespace Jellyfin.Plugin.Vgmdb.Models;
+
+public class SearchResponseResultsAlbum
+{
+ [JsonPropertyName("catalog")]
+ public string Catalog { get; set; }
+
+ [JsonPropertyName("link")]
+ public string Link { get; set; }
+
+ [JsonPropertyName("release_date")]
+ public string ReleaseDate { get; set; }
+
+ [JsonPropertyName("titles")]
+ public LocalizedString Titles { get; set; }
+
+ public int Id => int.Parse(Link.Replace("album/", string.Empty, StringComparison.OrdinalIgnoreCase), CultureInfo.InvariantCulture);
+}
diff --git a/Jellyfin.Plugin.Vgmdb/Models/SearchResponseResultsArtist.cs b/Jellyfin.Plugin.Vgmdb/Models/SearchResponseResultsArtist.cs
new file mode 100644
index 0000000..3cfd4d3
--- /dev/null
+++ b/Jellyfin.Plugin.Vgmdb/Models/SearchResponseResultsArtist.cs
@@ -0,0 +1,20 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Text.Json.Serialization;
+
+namespace Jellyfin.Plugin.Vgmdb.Models;
+
+public class SearchResponseResultsArtist
+{
+ [JsonPropertyName("aliases")]
+ public IReadOnlyList Aliases { get; set; } = Array.Empty();
+
+ [JsonPropertyName("link")]
+ public string Link { get; set; }
+
+ [JsonPropertyName("names")]
+ public LocalizedString Names { get; set; }
+
+ public int Id => int.Parse(Link.Replace("artist/", string.Empty, StringComparison.OrdinalIgnoreCase), CultureInfo.InvariantCulture);
+}
diff --git a/Jellyfin.Plugin.Vgmdb/PluginConfiguration.cs b/Jellyfin.Plugin.Vgmdb/PluginConfiguration.cs
new file mode 100644
index 0000000..03186ba
--- /dev/null
+++ b/Jellyfin.Plugin.Vgmdb/PluginConfiguration.cs
@@ -0,0 +1,8 @@
+using MediaBrowser.Model.Plugins;
+
+namespace Jellyfin.Plugin.Vgmdb;
+
+///
+public class PluginConfiguration : BasePluginConfiguration
+{
+}
diff --git a/Jellyfin.Plugin.Vgmdb/Providers/Images/VgmdbAlbumImageProvider.cs b/Jellyfin.Plugin.Vgmdb/Providers/Images/VgmdbAlbumImageProvider.cs
new file mode 100644
index 0000000..61abee7
--- /dev/null
+++ b/Jellyfin.Plugin.Vgmdb/Providers/Images/VgmdbAlbumImageProvider.cs
@@ -0,0 +1,66 @@
+using System.Collections.Generic;
+using System.Globalization;
+using System.Net.Http;
+using System.Threading;
+using System.Threading.Tasks;
+using Jellyfin.Plugin.Vgmdb.ExternalIds;
+using MediaBrowser.Common.Net;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Entities.Audio;
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Providers;
+
+namespace Jellyfin.Plugin.Vgmdb.Providers.Images;
+
+public class VgmdbAlbumImageProvider : IRemoteImageProvider
+{
+ private readonly IHttpClientFactory _httpClientFactory;
+ private readonly VgmdbApi _api;
+
+ public VgmdbAlbumImageProvider(IHttpClientFactory httpClientFactory)
+ {
+ _httpClientFactory = httpClientFactory;
+ _api = new VgmdbApi(httpClientFactory);
+ }
+
+ public string Name => "VGMdb";
+
+ public Task GetImageResponse(string url, CancellationToken cancellationToken)
+ {
+ return _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken);
+ }
+
+ public async Task> GetImages(BaseItem item, CancellationToken cancellationToken)
+ {
+ var images = new List();
+
+ var id = item.GetProviderId(VgmdbAlbumExternalId.ExternalId);
+
+ // todo use a search to find id
+ if (id == null)
+ {
+ return images;
+ }
+
+ var album = await _api.GetAlbumById(int.Parse(id, CultureInfo.InvariantCulture), cancellationToken).ConfigureAwait(false);
+
+ images.Add(new RemoteImageInfo
+ {
+ Url = album.PictureFull,
+ ThumbnailUrl = album.PictureSmall
+ });
+
+ return images;
+ }
+
+ public IEnumerable GetSupportedImages(BaseItem item)
+ {
+ return new List
+ {
+ ImageType.Primary
+ };
+ }
+
+ public bool Supports(BaseItem item) => item is MusicAlbum;
+}
diff --git a/Jellyfin.Plugin.Vgmdb/Providers/Images/VgmdbArtistImageProvider.cs b/Jellyfin.Plugin.Vgmdb/Providers/Images/VgmdbArtistImageProvider.cs
new file mode 100644
index 0000000..48a490c
--- /dev/null
+++ b/Jellyfin.Plugin.Vgmdb/Providers/Images/VgmdbArtistImageProvider.cs
@@ -0,0 +1,66 @@
+using System.Collections.Generic;
+using System.Globalization;
+using System.Net.Http;
+using System.Threading;
+using System.Threading.Tasks;
+using Jellyfin.Plugin.Vgmdb.ExternalIds;
+using MediaBrowser.Common.Net;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Entities.Audio;
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Providers;
+
+namespace Jellyfin.Plugin.Vgmdb.Providers.Images;
+
+public class VgmdbArtistImageProvider : IRemoteImageProvider
+{
+ private readonly IHttpClientFactory _httpClientFactory;
+ private readonly VgmdbApi _api;
+
+ public VgmdbArtistImageProvider(IHttpClientFactory httpClientFactory)
+ {
+ _httpClientFactory = httpClientFactory;
+ _api = new VgmdbApi(httpClientFactory);
+ }
+
+ public string Name => "VGMdb";
+
+ public Task GetImageResponse(string url, CancellationToken cancellationToken)
+ {
+ return _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken);
+ }
+
+ public async Task> GetImages(BaseItem item, CancellationToken cancellationToken)
+ {
+ var images = new List();
+
+ var id = item.GetProviderId(VgmdbArtistExternalId.ExternalId);
+
+ // todo use a search to find id
+ if (id == null)
+ {
+ return images;
+ }
+
+ var artist = await _api.GetArtistByIdAsync(int.Parse(id, CultureInfo.InvariantCulture), cancellationToken).ConfigureAwait(false);
+
+ images.Add(new RemoteImageInfo
+ {
+ Url = artist.PictureFull,
+ ThumbnailUrl = artist.PictureSmall
+ });
+
+ return images;
+ }
+
+ public IEnumerable GetSupportedImages(BaseItem item)
+ {
+ return new List
+ {
+ ImageType.Primary
+ };
+ }
+
+ public bool Supports(BaseItem item) => item is MusicArtist;
+}
diff --git a/Jellyfin.Plugin.Vgmdb/Providers/Info/VgmdbAlbumProvider.cs b/Jellyfin.Plugin.Vgmdb/Providers/Info/VgmdbAlbumProvider.cs
new file mode 100644
index 0000000..eb69439
--- /dev/null
+++ b/Jellyfin.Plugin.Vgmdb/Providers/Info/VgmdbAlbumProvider.cs
@@ -0,0 +1,151 @@
+using System.Collections.Generic;
+using System.Globalization;
+using System.Net.Http;
+using System.Threading;
+using System.Threading.Tasks;
+using Jellyfin.Plugin.Vgmdb.ExternalIds;
+using MediaBrowser.Common.Net;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Entities.Audio;
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Providers;
+
+namespace Jellyfin.Plugin.Vgmdb.Providers.Info;
+
+public class VgmdbAlbumProvider : IRemoteMetadataProvider
+{
+ private readonly IHttpClientFactory _httpClientFactory;
+ private readonly VgmdbApi _api;
+
+ public VgmdbAlbumProvider(IHttpClientFactory httpClientFactory)
+ {
+ _httpClientFactory = httpClientFactory;
+ _api = new VgmdbApi(httpClientFactory);
+ }
+
+ public string Name => "VGMdb";
+
+ public Task GetImageResponse(string url, CancellationToken cancellationToken)
+ {
+ return _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken);
+ }
+
+ public async Task GetAlbumByIdAsync(int id, CancellationToken cancellationToken)
+ {
+ var response = await _api.GetAlbumById(id, cancellationToken).ConfigureAwait(false);
+
+ if (response == null)
+ {
+ return null;
+ }
+
+ var album = new MusicAlbum
+ {
+ ProviderIds =
+ {
+ [VgmdbAlbumExternalId.ExternalId] = response.Id.ToString(CultureInfo.InvariantCulture)
+ },
+ Name = response.Names.GetPreferred()
+ };
+
+ // todo better date parsing
+ _ = int.TryParse(response.ReleaseDate.Split('-')[0], out var productionYear);
+ if (productionYear > 0)
+ {
+ album.ProductionYear = productionYear;
+ }
+
+ var image = new ItemImageInfo
+ {
+ Path = response.PictureFull,
+ Type = ImageType.Primary
+ };
+ album.SetImage(image, 0);
+
+ album.Overview = response.Notes;
+
+ if (response.Categories != null)
+ {
+ foreach (var category in response.Categories)
+ {
+ album.AddGenre(category);
+ }
+ }
+
+ if (response.Organizations != null)
+ {
+ foreach (var organisation in response.Organizations)
+ {
+ album.AddStudio(organisation.Names.GetPreferred());
+ }
+ }
+
+ return album;
+ }
+
+ public async Task GetIdAsync(AlbumInfo info, CancellationToken cancellationToken)
+ {
+ var providedId = info.GetProviderId(VgmdbAlbumExternalId.ExternalId);
+ if (providedId != null)
+ {
+ return int.Parse(providedId, CultureInfo.InvariantCulture);
+ }
+
+ var searchResults = await GetSearchResults(info, cancellationToken).ConfigureAwait(false);
+
+ foreach (var result in searchResults)
+ {
+ var id = result.GetProviderId(VgmdbAlbumExternalId.ExternalId);
+
+ if (id != null)
+ {
+ return int.Parse(id, CultureInfo.InvariantCulture);
+ }
+ }
+
+ return null;
+ }
+
+ public async Task> GetMetadata(AlbumInfo info, CancellationToken cancellationToken)
+ {
+ var id = await GetIdAsync(info, cancellationToken).ConfigureAwait(false);
+
+ if (id != null)
+ {
+ return new MetadataResult
+ {
+ Item = await GetAlbumByIdAsync(id.Value, cancellationToken).ConfigureAwait(false)
+ };
+ }
+
+ return new MetadataResult();
+ }
+
+ public async Task> GetSearchResults(AlbumInfo searchInfo, CancellationToken cancellationToken)
+ {
+ var response = await _api.GetSearchResultsAsync(searchInfo.Name, cancellationToken).ConfigureAwait(false);
+
+ var searchResults = new List();
+ if (response == null)
+ {
+ return null;
+ }
+
+ foreach (var albumEntry in response.Results.Albums)
+ {
+ var album = await GetAlbumByIdAsync(albumEntry.Id, cancellationToken).ConfigureAwait(false);
+ var result = new RemoteSearchResult
+ {
+ ProviderIds = album.ProviderIds,
+ Name = album.Name,
+ ProductionYear = album.ProductionYear,
+ ImageUrl = album.PrimaryImagePath
+ };
+
+ searchResults.Add(result);
+ }
+
+ return searchResults;
+ }
+}
diff --git a/Jellyfin.Plugin.Vgmdb/Providers/Info/VgmdbArtistProvider.cs b/Jellyfin.Plugin.Vgmdb/Providers/Info/VgmdbArtistProvider.cs
new file mode 100644
index 0000000..23d36ad
--- /dev/null
+++ b/Jellyfin.Plugin.Vgmdb/Providers/Info/VgmdbArtistProvider.cs
@@ -0,0 +1,127 @@
+using System.Collections.Generic;
+using System.Globalization;
+using System.Net.Http;
+using System.Threading;
+using System.Threading.Tasks;
+using Jellyfin.Plugin.Vgmdb.ExternalIds;
+using MediaBrowser.Common.Net;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Entities.Audio;
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Providers;
+
+namespace Jellyfin.Plugin.Vgmdb.Providers.Info;
+
+public class VgmdbArtistProvider : IRemoteMetadataProvider
+{
+ private readonly IHttpClientFactory _httpClientFactory;
+ private readonly VgmdbApi _api;
+
+ public VgmdbArtistProvider(IHttpClientFactory httpClientFactory)
+ {
+ _httpClientFactory = httpClientFactory;
+ _api = new VgmdbApi(httpClientFactory);
+ }
+
+ public string Name => "VGMdb";
+
+ public Task GetImageResponse(string url, CancellationToken cancellationToken)
+ {
+ return _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken);
+ }
+
+ public async Task GetArtistByIdAsync(int id, CancellationToken cancellationToken)
+ {
+ var response = await _api.GetArtistByIdAsync(id, cancellationToken).ConfigureAwait(false);
+
+ if (response == null)
+ {
+ return null;
+ }
+
+ var artist = new MusicArtist
+ {
+ ProviderIds =
+ {
+ [VgmdbArtistExternalId.ExternalId] = response.Id.ToString(CultureInfo.InvariantCulture)
+ },
+ Name = response.Name
+ };
+
+ var image = new ItemImageInfo
+ {
+ Path = response.PictureFull,
+ Type = ImageType.Primary
+ };
+ artist.SetImage(image, 0);
+
+ artist.Overview = response.Notes;
+
+ return artist;
+ }
+
+ public async Task GetIdAsync(ArtistInfo info, CancellationToken cancellationToken)
+ {
+ var providedId = info.GetProviderId(VgmdbArtistExternalId.ExternalId);
+ if (providedId != null)
+ {
+ return int.Parse(providedId, CultureInfo.InvariantCulture);
+ }
+
+ var searchResults = await GetSearchResults(info, cancellationToken).ConfigureAwait(false);
+
+ foreach (var result in searchResults)
+ {
+ var id = result.GetProviderId(VgmdbArtistExternalId.ExternalId);
+
+ if (id != null)
+ {
+ return int.Parse(id, CultureInfo.InvariantCulture);
+ }
+ }
+
+ return null;
+ }
+
+ public async Task> GetMetadata(ArtistInfo info, CancellationToken cancellationToken)
+ {
+ var id = await GetIdAsync(info, cancellationToken).ConfigureAwait(false);
+
+ if (id != null)
+ {
+ return new MetadataResult
+ {
+ Item = await GetArtistByIdAsync(id.Value, cancellationToken).ConfigureAwait(false)
+ };
+ }
+
+ return new MetadataResult();
+ }
+
+ public async Task> GetSearchResults(ArtistInfo searchInfo, CancellationToken cancellationToken)
+ {
+ var response = await _api.GetSearchResultsAsync(searchInfo.Name, cancellationToken).ConfigureAwait(false);
+ if (response == null)
+ {
+ return null;
+ }
+
+ var searchResults = new List();
+
+ foreach (var artistEntry in response.Results.Artists)
+ {
+ var artist = await GetArtistByIdAsync(artistEntry.Id, cancellationToken).ConfigureAwait(false);
+ var result = new RemoteSearchResult
+ {
+ ProviderIds = artist.ProviderIds,
+ Name = artist.Name,
+ ImageUrl = artist.PrimaryImagePath
+ };
+
+ searchResults.Add(result);
+ }
+
+ return searchResults;
+ }
+}
diff --git a/Jellyfin.Plugin.Vgmdb/VgmdbApi.cs b/Jellyfin.Plugin.Vgmdb/VgmdbApi.cs
new file mode 100644
index 0000000..4876e7f
--- /dev/null
+++ b/Jellyfin.Plugin.Vgmdb/VgmdbApi.cs
@@ -0,0 +1,41 @@
+using System.Net;
+using System.Net.Http;
+using System.Net.Http.Json;
+using System.Threading;
+using System.Threading.Tasks;
+using Jellyfin.Plugin.Vgmdb.Models;
+using MediaBrowser.Common.Net;
+
+namespace Jellyfin.Plugin.Vgmdb;
+
+public class VgmdbApi
+{
+ private const string RootUrl = @"https://vgmdb.info/";
+ private readonly IHttpClientFactory _httpClientFactory;
+
+ public VgmdbApi(IHttpClientFactory httpClientFactory)
+ {
+ _httpClientFactory = httpClientFactory;
+ }
+
+ public async Task GetArtistByIdAsync(int id, CancellationToken cancellationToken)
+ {
+ var httpClient = _httpClientFactory.CreateClient(NamedClient.Default);
+ using var response = await httpClient.GetAsync(RootUrl + "/artist/" + id + "?format=json", cancellationToken).ConfigureAwait(false);
+ return await response.Content.ReadFromJsonAsync(cancellationToken: cancellationToken).ConfigureAwait(false);
+ }
+
+ public async Task GetAlbumById(int id, CancellationToken cancellationToken)
+ {
+ var httpClient = _httpClientFactory.CreateClient(NamedClient.Default);
+ using var response = await httpClient.GetAsync(RootUrl + "/album/" + id + "?format=json", cancellationToken).ConfigureAwait(false);
+ return await response.Content.ReadFromJsonAsync(cancellationToken: cancellationToken).ConfigureAwait(false);
+ }
+
+ public async Task GetSearchResultsAsync(string name, CancellationToken cancellationToken)
+ {
+ var httpClient = _httpClientFactory.CreateClient(NamedClient.Default);
+ using var response = await httpClient.GetAsync(RootUrl + "/search?format=json&q=" + WebUtility.UrlEncode(name), cancellationToken).ConfigureAwait(false);
+ return await response.Content.ReadFromJsonAsync(cancellationToken: cancellationToken).ConfigureAwait(false);
+ }
+}
diff --git a/Jellyfin.Plugin.Vgmdb/VgmdbPlugin.cs b/Jellyfin.Plugin.Vgmdb/VgmdbPlugin.cs
new file mode 100644
index 0000000..85cb996
--- /dev/null
+++ b/Jellyfin.Plugin.Vgmdb/VgmdbPlugin.cs
@@ -0,0 +1,21 @@
+using System;
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.Plugins;
+using MediaBrowser.Model.Serialization;
+
+namespace Jellyfin.Plugin.Vgmdb;
+
+///
+public class VgmdbPlugin : BasePlugin
+{
+ public VgmdbPlugin(IApplicationPaths applicationPaths, IXmlSerializer xmlSerializer)
+ : base(applicationPaths, xmlSerializer)
+ {
+ }
+
+ ///
+ public override string Name => "VGMdb";
+
+ ///
+ public override Guid Id => Guid.Parse("44616595-5798-47ad-8658-3c09f3030505");
+}
diff --git a/jellyfin.ruleset b/jellyfin.ruleset
new file mode 100644
index 0000000..8af791c
--- /dev/null
+++ b/jellyfin.ruleset
@@ -0,0 +1,108 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/ExternalIds/VgmdbAlbumExternalId.cs b/src/ExternalIds/VgmdbAlbumExternalId.cs
deleted file mode 100644
index 7e6b103..0000000
--- a/src/ExternalIds/VgmdbAlbumExternalId.cs
+++ /dev/null
@@ -1,24 +0,0 @@
-using MediaBrowser.Controller.Entities.Audio;
-using MediaBrowser.Controller.Providers;
-using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Providers;
-
-namespace Jellyfin.Plugin.Vgmdb.ExternalIds
-{
- ///
- // ReSharper disable once ClassNeverInstantiated.Global
- public class VgmdbAlbumExternalId : IExternalId
- {
- public const string ExternalId = "VGMdbAlbum";
-
- public string ProviderName => "VGMdb Album";
-
- public string Key => ExternalId;
-
- public ExternalIdMediaType? Type => ExternalIdMediaType.Album;
-
- public string UrlFormatString => "https://vgmdb.net/album/{0}";
-
- public bool Supports(IHasProviderIds item) => item is MusicAlbum;
- }
-}
\ No newline at end of file
diff --git a/src/ExternalIds/VgmdbArtistExternalId.cs b/src/ExternalIds/VgmdbArtistExternalId.cs
deleted file mode 100644
index cceec03..0000000
--- a/src/ExternalIds/VgmdbArtistExternalId.cs
+++ /dev/null
@@ -1,24 +0,0 @@
-using MediaBrowser.Controller.Entities.Audio;
-using MediaBrowser.Controller.Providers;
-using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Providers;
-
-namespace Jellyfin.Plugin.Vgmdb.ExternalIds
-{
- ///
- // ReSharper disable once ClassNeverInstantiated.Global
- public class VgmdbArtistExternalId : IExternalId
- {
- public const string ExternalId = "VGMdbArtist";
-
- public string ProviderName => "VGMdb Artist";
-
- public string Key => ExternalId;
-
- public ExternalIdMediaType? Type => ExternalIdMediaType.Album;
-
- public string UrlFormatString => "https://vgmdb.net/artist/{0}";
-
- public bool Supports(IHasProviderIds item) => item is MusicArtist;
- }
-}
\ No newline at end of file
diff --git a/src/Models/AlbumResponse.cs b/src/Models/AlbumResponse.cs
deleted file mode 100644
index 99057de..0000000
--- a/src/Models/AlbumResponse.cs
+++ /dev/null
@@ -1,21 +0,0 @@
-using System.Collections.Generic;
-
-namespace Jellyfin.Plugin.Vgmdb.Models
-{
- public class AlbumResponse
- {
- public LocalizedString names { get; set; }
- public string picture_full { get; set; }
- public string picture_small { get; set; }
- public string picture_thumb { get; set; }
- public string link { get; set; }
- public string notes { get; set; }
-
- public string release_date { get; set; }
-
- public List categories { get; set; }
- public List organizations { get; set; }
-
- public int Id => int.Parse(link.Replace("album/", ""));
- }
-}
\ No newline at end of file
diff --git a/src/Models/ArtistResponse.cs b/src/Models/ArtistResponse.cs
deleted file mode 100644
index 3399141..0000000
--- a/src/Models/ArtistResponse.cs
+++ /dev/null
@@ -1,13 +0,0 @@
-namespace Jellyfin.Plugin.Vgmdb.Models
-{
- public class ArtistResponse
- {
- public string name { get; set; }
- public string picture_full { get; set; }
- public string picture_small { get; set; }
- public string link { get; set; }
- public string notes { get; set; }
-
- public int Id => int.Parse(link.Replace("artist/", ""));
- }
-}
\ No newline at end of file
diff --git a/src/Models/LocalizedString.cs b/src/Models/LocalizedString.cs
deleted file mode 100644
index bb8d5ac..0000000
--- a/src/Models/LocalizedString.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-namespace Jellyfin.Plugin.Vgmdb.Models
-{
- public class LocalizedString
- {
- public string en { get; set; }
- public string ja { get; set; }
- public string jaLatn { get; set; }
-
- public string GetPreferred()
- {
- return jaLatn ?? en ?? ja;
- }
- }
-}
\ No newline at end of file
diff --git a/src/Models/Organisation.cs b/src/Models/Organisation.cs
deleted file mode 100644
index 17f687f..0000000
--- a/src/Models/Organisation.cs
+++ /dev/null
@@ -1,11 +0,0 @@
-namespace Jellyfin.Plugin.Vgmdb.Models
-{
- public class Organisation
- {
- public string link { get; set; }
- public LocalizedString names { get; set; }
- public string role { get; set; }
-
- public int Id => int.Parse(link.Replace("org/", ""));
- }
-}
\ No newline at end of file
diff --git a/src/Models/SearchResponse.cs b/src/Models/SearchResponse.cs
deleted file mode 100644
index 01b4ef9..0000000
--- a/src/Models/SearchResponse.cs
+++ /dev/null
@@ -1,7 +0,0 @@
-namespace Jellyfin.Plugin.Vgmdb.Models
-{
- public class SearchResponse
- {
- public SearchResponseResults results { get; set; }
- }
-}
\ No newline at end of file
diff --git a/src/Models/SearchResponseResults.cs b/src/Models/SearchResponseResults.cs
deleted file mode 100644
index 1d4fd21..0000000
--- a/src/Models/SearchResponseResults.cs
+++ /dev/null
@@ -1,10 +0,0 @@
-using System.Collections.Generic;
-
-namespace Jellyfin.Plugin.Vgmdb.Models
-{
- public class SearchResponseResults
- {
- public List albums { get; set; }
- public List artists { get; set; }
- }
-}
\ No newline at end of file
diff --git a/src/Models/SearchResponseResultsAlbum.cs b/src/Models/SearchResponseResultsAlbum.cs
deleted file mode 100644
index 6ce02f9..0000000
--- a/src/Models/SearchResponseResultsAlbum.cs
+++ /dev/null
@@ -1,12 +0,0 @@
-namespace Jellyfin.Plugin.Vgmdb.Models
-{
- public class SearchResponseResultsAlbum
- {
- public string catalog { get; set; }
- public string link { get; set; }
- public string release_date { get; set; }
- public LocalizedString titles { get; set; }
-
- public int Id => int.Parse(link.Replace("album/", ""));
- }
-}
\ No newline at end of file
diff --git a/src/Models/SearchResponseResultsArtist.cs b/src/Models/SearchResponseResultsArtist.cs
deleted file mode 100644
index fed3ffd..0000000
--- a/src/Models/SearchResponseResultsArtist.cs
+++ /dev/null
@@ -1,13 +0,0 @@
-using System.Collections.Generic;
-
-namespace Jellyfin.Plugin.Vgmdb.Models
-{
- public class SearchResponseResultsArtist
- {
- public List aliases { get; set; }
- public string link { get; set; }
- public LocalizedString names { get; set; }
-
- public int Id => int.Parse(link.Replace("artist/", ""));
- }
-}
\ No newline at end of file
diff --git a/src/Plugin.cs b/src/Plugin.cs
deleted file mode 100644
index 9307b5c..0000000
--- a/src/Plugin.cs
+++ /dev/null
@@ -1,19 +0,0 @@
-using System;
-using MediaBrowser.Common.Configuration;
-using MediaBrowser.Common.Plugins;
-using MediaBrowser.Model.Serialization;
-
-namespace Jellyfin.Plugin.Vgmdb
-{
- ///
- // ReSharper disable once UnusedMember.Global
- public class Plugin : BasePlugin
- {
- public Plugin(IApplicationPaths applicationPaths, IXmlSerializer xmlSerializer) : base(applicationPaths, xmlSerializer)
- {
- }
-
- public override string Name => "VGMdb";
- public override Guid Id => Guid.Parse("44616595-5798-47ad-8658-3c09f3030505");
- }
-}
\ No newline at end of file
diff --git a/src/PluginConfiguration.cs b/src/PluginConfiguration.cs
deleted file mode 100644
index f193951..0000000
--- a/src/PluginConfiguration.cs
+++ /dev/null
@@ -1,10 +0,0 @@
-using MediaBrowser.Model.Plugins;
-
-namespace Jellyfin.Plugin.Vgmdb
-{
- ///
- // ReSharper disable once ClassNeverInstantiated.Global
- public class PluginConfiguration : BasePluginConfiguration
- {
- }
-}
\ No newline at end of file
diff --git a/src/Providers/Images/VgmdbAlbumImageProvider.cs b/src/Providers/Images/VgmdbAlbumImageProvider.cs
deleted file mode 100644
index 7bad4af..0000000
--- a/src/Providers/Images/VgmdbAlbumImageProvider.cs
+++ /dev/null
@@ -1,63 +0,0 @@
-using System.Collections.Generic;
-using System.Net.Http;
-using System.Threading;
-using System.Threading.Tasks;
-using Jellyfin.Plugin.Vgmdb.ExternalIds;
-using MediaBrowser.Common.Net;
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Entities.Audio;
-using MediaBrowser.Controller.Providers;
-using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Providers;
-using MediaBrowser.Model.Serialization;
-
-namespace Jellyfin.Plugin.Vgmdb.Providers.Images
-{
- public class VgmdbAlbumImageProvider : IRemoteImageProvider
- {
- private readonly IHttpClientFactory _httpClientFactory;
- private readonly VgmdbApi _api;
-
- public VgmdbAlbumImageProvider(IHttpClientFactory httpClientFactory)
- {
- _httpClientFactory = httpClientFactory;
- _api = new VgmdbApi(httpClientFactory);
- }
-
- public string Name => "VGMdb";
-
- public Task GetImageResponse(string url, CancellationToken cancellationToken)
- {
- return _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken);
- }
-
- public async Task> GetImages(BaseItem item, CancellationToken cancellationToken)
- {
- var images = new List();
-
- var id = item.GetProviderId(VgmdbAlbumExternalId.ExternalId);
-
- //todo use a search to find id
- if (id == null) return images;
- var album = await _api.GetAlbumById(int.Parse(id), cancellationToken);
-
- images.Add(new RemoteImageInfo
- {
- Url = album.picture_full,
- ThumbnailUrl = album.picture_small
- });
-
- return images;
- }
-
- public IEnumerable GetSupportedImages(BaseItem item)
- {
- return new List
- {
- ImageType.Primary
- };
- }
-
- public bool Supports(BaseItem item) => item is MusicAlbum;
- }
-}
diff --git a/src/Providers/Images/VgmdbArtistImageProvider.cs b/src/Providers/Images/VgmdbArtistImageProvider.cs
deleted file mode 100644
index de84cc7..0000000
--- a/src/Providers/Images/VgmdbArtistImageProvider.cs
+++ /dev/null
@@ -1,64 +0,0 @@
-using System.Collections.Generic;
-using System.Net.Http;
-using System.Threading;
-using System.Threading.Tasks;
-using Jellyfin.Plugin.Vgmdb.ExternalIds;
-using MediaBrowser.Common.Net;
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Entities.Audio;
-using MediaBrowser.Controller.Providers;
-using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Providers;
-using MediaBrowser.Model.Serialization;
-
-namespace Jellyfin.Plugin.Vgmdb.Providers.Images
-{
- public class VgmdbArtistImageProvider : IRemoteImageProvider
- {
- private readonly IHttpClientFactory _httpClientFactory;
- private readonly VgmdbApi _api;
-
- public VgmdbArtistImageProvider(IHttpClientFactory httpClientFactory)
- {
- _httpClientFactory = httpClientFactory;
- _api = new VgmdbApi(httpClientFactory);
- }
-
- public string Name => "VGMdb";
-
- public Task GetImageResponse(string url, CancellationToken cancellationToken)
- {
- return _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url);
- }
-
- public async Task> GetImages(BaseItem item, CancellationToken cancellationToken)
- {
- var images = new List();
-
- var id = item.GetProviderId(VgmdbArtistExternalId.ExternalId);
-
- //todo use a search to find id
- if (id == null) return images;
-
- var artist = await _api.GetArtistById(int.Parse(id), cancellationToken);
-
- images.Add(new RemoteImageInfo
- {
- Url = artist.picture_full,
- ThumbnailUrl = artist.picture_small
- });
-
- return images;
- }
-
- public IEnumerable GetSupportedImages(BaseItem item)
- {
- return new List
- {
- ImageType.Primary
- };
- }
-
- public bool Supports(BaseItem item) => item is MusicArtist;
- }
-}
diff --git a/src/Providers/Info/VgmdbAlbumProvider.cs b/src/Providers/Info/VgmdbAlbumProvider.cs
deleted file mode 100644
index de7a4ea..0000000
--- a/src/Providers/Info/VgmdbAlbumProvider.cs
+++ /dev/null
@@ -1,138 +0,0 @@
-using System.Collections.Generic;
-using System.Net.Http;
-using System.Threading;
-using System.Threading.Tasks;
-using Jellyfin.Plugin.Vgmdb.ExternalIds;
-using MediaBrowser.Common.Net;
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Entities.Audio;
-using MediaBrowser.Controller.Providers;
-using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Providers;
-using MediaBrowser.Model.Serialization;
-
-namespace Jellyfin.Plugin.Vgmdb.Providers.Info
-{
- // todo: implement IHasOrder, but find out what it does first
- public class VgmdbAlbumProvider : IRemoteMetadataProvider
- {
- private readonly IHttpClientFactory _httpClientFactory;
- private readonly VgmdbApi _api;
-
- public VgmdbAlbumProvider(IHttpClientFactory httpClientFactory)
- {
- _httpClientFactory = httpClientFactory;
- _api = new VgmdbApi(httpClientFactory);
- }
-
- public string Name => "VGMdb";
-
- public Task GetImageResponse(string url, CancellationToken cancellationToken)
- {
- return _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url);
- }
-
- public async Task GetAlbumById(int id, CancellationToken cancellationToken)
- {
- var response = await _api.GetAlbumById(id, cancellationToken);
-
- if (response == null) return null;
-
- var album = new MusicAlbum
- {
- ProviderIds =
- {
- [VgmdbAlbumExternalId.ExternalId] = response.Id.ToString()
- },
- Name = response.names.GetPreferred()
- };
-
- //todo better date parsing
- int.TryParse(response.release_date.Split('-')[0], out var productionYear);
- if (productionYear > 0) album.ProductionYear = productionYear;
-
- var image = new ItemImageInfo
- {
- Path = response.picture_full,
- Type = ImageType.Primary
- };
- album.SetImage(image, 0);
-
- album.Overview = response.notes;
-
- if (response.categories != null)
- {
- foreach (var category in response.categories)
- {
- album.AddGenre(category);
- }
- }
-
- if (response.organizations != null)
- {
- foreach (var organisation in response.organizations)
- {
- album.AddStudio(organisation.names.GetPreferred());
- }
- }
-
- return album;
- }
-
- public async Task GetId(AlbumInfo info, CancellationToken cancellationToken)
- {
- var providedId = info.GetProviderId(VgmdbAlbumExternalId.ExternalId);
- if (providedId != null) return int.Parse(providedId);
-
- var searchResults = await GetSearchResults(info, cancellationToken);
-
- foreach (var result in searchResults)
- {
- var id = result.GetProviderId(VgmdbAlbumExternalId.ExternalId);
-
- if (id != null) return int.Parse(id);
- }
-
- return null;
- }
-
- public async Task> GetMetadata(AlbumInfo info, CancellationToken cancellationToken)
- {
- var id = await GetId(info, cancellationToken);
-
- if (id != null)
- {
- return new MetadataResult
- {
- Item = await GetAlbumById((int) id, cancellationToken)
- };
- }
-
- return new MetadataResult();
- }
-
- public async Task> GetSearchResults(AlbumInfo searchInfo, CancellationToken cancellationToken)
- {
- var response = await _api.GetSearchResults(searchInfo.Name, cancellationToken);
-
- var searchResults = new List();
- if (response == null) return null;
-
- foreach (var albumEntry in response.results.albums)
- {
- var album = await GetAlbumById(albumEntry.Id, cancellationToken);
- var result = new RemoteSearchResult
- {
- ProviderIds = album.ProviderIds,
- Name = album.Name,
- ProductionYear = album.ProductionYear,
- ImageUrl = album.PrimaryImagePath
- };
-
- searchResults.Add(result);
- }
-
- return searchResults;
- }
- }
-}
diff --git a/src/Providers/Info/VgmdbArtistProvider.cs b/src/Providers/Info/VgmdbArtistProvider.cs
deleted file mode 100644
index 746bc73..0000000
--- a/src/Providers/Info/VgmdbArtistProvider.cs
+++ /dev/null
@@ -1,117 +0,0 @@
-using System.Collections.Generic;
-using System.Net.Http;
-using System.Threading;
-using System.Threading.Tasks;
-using Jellyfin.Plugin.Vgmdb.ExternalIds;
-using MediaBrowser.Common.Net;
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Entities.Audio;
-using MediaBrowser.Controller.Providers;
-using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Providers;
-using MediaBrowser.Model.Serialization;
-
-namespace Jellyfin.Plugin.Vgmdb.Providers.Info
-{
- // todo: implement IHasOrder, but find out what it does first
- public class VgmdbArtistProvider : IRemoteMetadataProvider
- {
- private readonly IHttpClientFactory _httpClientFactory;
- private readonly VgmdbApi _api;
-
- public VgmdbArtistProvider(IHttpClientFactory httpClientFactory)
- {
- _httpClientFactory = httpClientFactory;
- _api = new VgmdbApi(httpClientFactory);
- }
-
- public string Name => "VGMdb";
-
- public Task GetImageResponse(string url, CancellationToken cancellationToken)
- {
- return _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url);
- }
-
- public async Task GetArtistById(int id, CancellationToken cancellationToken)
- {
- var response = await _api.GetArtistById(id, cancellationToken);
-
- if (response == null) return null;
-
- var artist = new MusicArtist
- {
- ProviderIds =
- {
- [VgmdbArtistExternalId.ExternalId] = response.Id.ToString()
- },
- Name = response.name
- };
-
- var image = new ItemImageInfo
- {
- Path = response.picture_full,
- Type = ImageType.Primary
- };
- artist.SetImage(image, 0);
-
- artist.Overview = response.notes;
-
- return artist;
- }
-
- public async Task GetId(ArtistInfo info, CancellationToken cancellationToken)
- {
- var providedId = info.GetProviderId(VgmdbArtistExternalId.ExternalId);
- if (providedId != null) return int.Parse(providedId);
-
- var searchResults = await GetSearchResults(info, cancellationToken);
-
- foreach (var result in searchResults)
- {
- var id = result.GetProviderId(VgmdbArtistExternalId.ExternalId);
-
- if (id != null) return int.Parse(id);
- }
-
- return null;
- }
-
- public async Task> GetMetadata(ArtistInfo info, CancellationToken cancellationToken)
- {
- var id = await GetId(info, cancellationToken);
-
- if (id != null)
- {
- return new MetadataResult
- {
- Item = await GetArtistById((int) id, cancellationToken)
- };
- }
-
- return new MetadataResult();
- }
-
- public async Task> GetSearchResults(ArtistInfo searchInfo, CancellationToken cancellationToken)
- {
- var response = await _api.GetSearchResults(searchInfo.Name, cancellationToken);
-
- var searchResults = new List();
- if (response == null) return null;
-
- foreach (var artistEntry in response.results.artists)
- {
- var artist = await GetArtistById(artistEntry.Id, cancellationToken);
- var result = new RemoteSearchResult
- {
- ProviderIds = artist.ProviderIds,
- Name = artist.Name,
- ImageUrl = artist.PrimaryImagePath
- };
-
- searchResults.Add(result);
- }
-
- return searchResults;
- }
- }
-}
diff --git a/src/VgmdbApi.cs b/src/VgmdbApi.cs
deleted file mode 100644
index abd093c..0000000
--- a/src/VgmdbApi.cs
+++ /dev/null
@@ -1,52 +0,0 @@
-using System.Net;
-using System.Net.Http;
-using System.Text.Json;
-using System.Threading;
-using System.Threading.Tasks;
-using Jellyfin.Plugin.Vgmdb.Models;
-using MediaBrowser.Common.Net;
-using MediaBrowser.Model.Serialization;
-
-namespace Jellyfin.Plugin.Vgmdb
-{
- public class VgmdbApi
- {
- private readonly IHttpClientFactory _httpClientFactory;
- private const string RootUrl = @"https://vgmdb.info/";
-
- public VgmdbApi(IHttpClientFactory httpClientFactory)
- {
- _httpClientFactory = httpClientFactory;
- }
-
- public async Task GetArtistById(int id, CancellationToken cancellationToken)
- {
- var httpClient = _httpClientFactory.CreateClient(NamedClient.Default);
- using (var response = await httpClient.GetAsync(RootUrl + "/artist/" + id + "?format=json", cancellationToken).ConfigureAwait(false))
- {
- await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
- return await JsonSerializer.DeserializeAsync(stream).ConfigureAwait(false);
- }
- }
-
- public async Task GetAlbumById(int id, CancellationToken cancellationToken)
- {
- var httpClient = _httpClientFactory.CreateClient(NamedClient.Default);
- using (var response = await httpClient.GetAsync(RootUrl + "/album/" + id + "?format=json", cancellationToken).ConfigureAwait(false))
- {
- await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
- return await JsonSerializer.DeserializeAsync(stream).ConfigureAwait(false);
- }
- }
-
- public async Task GetSearchResults(string name, CancellationToken cancellationToken)
- {
- var httpClient = _httpClientFactory.CreateClient(NamedClient.Default);
- using (var response = await httpClient.GetAsync(RootUrl + "/search?format=json&q=" + WebUtility.UrlEncode(name), cancellationToken).ConfigureAwait(false))
- {
- await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
- return await JsonSerializer.DeserializeAsync(stream).ConfigureAwait(false);
- }
- }
- }
-}