Refactor LbzRpcService and add HandleNewListenData method
Refactored the LbzRpcService class to improve code structure and efficiency. Moved `lastRecording` and `albumArtUrl` fields to class scope and removed their initialization from the loop. Enhanced album art URL handling with `TrySetAlbumArtUrl` and `SetAlbumArtUrl` methods. Prioritized MusicBrainz data and added fallback to YouTube thumbnails.
This commit is contained in:
parent
67a3549e7b
commit
832832c4d2
306
Program.cs
306
Program.cs
|
@ -8,6 +8,8 @@ using Topshelf;
|
|||
using System.Web;
|
||||
using MetaBrainz.MusicBrainz.Interfaces.Entities;
|
||||
using MetaBrainz.MusicBrainz.Interfaces.Searches;
|
||||
using MetaBrainz.ListenBrainz.Interfaces;
|
||||
using System.Net;
|
||||
|
||||
|
||||
public class LbzRpcService
|
||||
|
@ -17,6 +19,8 @@ public class LbzRpcService
|
|||
|
||||
readonly Thread t;
|
||||
bool running = false;
|
||||
private string? lastRecording;
|
||||
private string albumArtUrl = "";
|
||||
|
||||
public LbzRpcService()
|
||||
{
|
||||
|
@ -71,10 +75,6 @@ public class LbzRpcService
|
|||
|
||||
InitializeDiscordRpc();
|
||||
|
||||
string? lastRecording = null;
|
||||
List<Button> buttons = new List<Button>();
|
||||
string albumArtUrl = "";
|
||||
|
||||
while (running)
|
||||
{
|
||||
if (!connected)
|
||||
|
@ -88,7 +88,7 @@ public class LbzRpcService
|
|||
var ignoredPlayers = config_data["general"]["ignored_sources"].Split(",", StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
|
||||
|
||||
|
||||
MetaBrainz.ListenBrainz.Interfaces.IPlayingNow? listen = null;
|
||||
IPlayingNow? listen = null;
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -114,115 +114,11 @@ public class LbzRpcService
|
|||
var listenData = listen.Track?.Info;
|
||||
if (listenData != null)
|
||||
{
|
||||
if (listenData.AdditionalInfo.OriginUrl != null
|
||||
&& (listenData.AdditionalInfo.OriginUrl?.Host == "music.youtube.com" || listenData.AdditionalInfo.OriginUrl?.Host == "www.youtube.com")
|
||||
&& GetYoutubeId(listenData.AdditionalInfo.OriginUrl) != null
|
||||
&& lastRecording != GetYoutubeId(listenData.AdditionalInfo.OriginUrl))
|
||||
{
|
||||
lastRecording = GetYoutubeId(listenData.AdditionalInfo.OriginUrl);
|
||||
|
||||
Console.WriteLine("Searching for release {0} on MusicBrainz", listenData.Release);
|
||||
Query q = new("LBZ-DRPC", new Version(1, 0, 0));
|
||||
ISearchResult<IRelease>? release = null;
|
||||
|
||||
if (listenData.Release != null || listenData.Artist != null)
|
||||
{
|
||||
release = q.FindReleases(listenData.Release ?? listenData.Artist, 1).Results?.FirstOrDefault();
|
||||
if (release?.Item.CoverArtArchive == null || !release.Item.CoverArtArchive.Front)
|
||||
{
|
||||
if (release?.Item.Aliases != null)
|
||||
foreach (IAlias alias in release.Item.Aliases)
|
||||
{
|
||||
if (alias.Primary == true)
|
||||
{
|
||||
var r = q.FindReleases(alias.Name, 1).Results?.FirstOrDefault();
|
||||
if (release != null && release.Item.CoverArtArchive?.Front == true)
|
||||
{
|
||||
release = r;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
lastRecording = GetYoutubeId(listenData.AdditionalInfo.OriginUrl);
|
||||
|
||||
if (release != null)
|
||||
{
|
||||
albumArtUrl = "https://coverartarchive.org/release/" + release.Item.Id + "/front-250.jpg";
|
||||
//albumArtUrl = "https://coverartarchive.org/release/" + release?.Item.Id + "/front-250.jpg";
|
||||
}
|
||||
else
|
||||
{
|
||||
var youtubeId = GetYoutubeId(listenData.AdditionalInfo.OriginUrl);
|
||||
albumArtUrl = "https://img.youtube.com/vi/" + youtubeId + "/mqdefault.jpg";
|
||||
}
|
||||
}
|
||||
else if (lastRecording != listenData.AdditionalInfo?.RecordingId.ToString() && listenData.AdditionalInfo?.RecordingId != null) // MusicBrainz ID available
|
||||
{
|
||||
Console.WriteLine("Listening to {0} by {1}", listenData.Name, listenData.Artist);
|
||||
lastRecording = listenData.AdditionalInfo?.RecordingId.ToString();
|
||||
|
||||
buttons = [];
|
||||
|
||||
if (listenData.AdditionalInfo?.RecordingId != null)
|
||||
{
|
||||
buttons.Add(new Button() { Label = "Listen on MusicBrainz", Url = $"https://listenbrainz.org/player/?recording_mbids={listenData.AdditionalInfo?.RecordingId}" });
|
||||
}
|
||||
|
||||
buttons.Add(new Button() { Label = $"{username} on ListenBrainz", Url = $"https://listenbrainz.org/user/{username}" });
|
||||
|
||||
string? newAlbumArt = null;
|
||||
|
||||
if (config_data["general"]["prioritise_musicbrainz"] == "true" && listenData.AdditionalInfo?.ReleaseId != null)
|
||||
{
|
||||
newAlbumArt = "https://coverartarchive.org/release/" + listenData.AdditionalInfo?.ReleaseId + "/front-250.jpg";
|
||||
}
|
||||
else if (config_data["general"]["prioritise_musicbrainz"] == "true" && listenData.Release != null)
|
||||
{
|
||||
var release = FindMusicBrainzRelease(listenData.Release);
|
||||
newAlbumArt = "https://coverartarchive.org/release/" + release?.Item.Id + "/front-250.jpg";
|
||||
}
|
||||
|
||||
if (newAlbumArt == null)
|
||||
{
|
||||
if ((listenData.AdditionalInfo?.OriginUrl?.ToString().Contains("youtube") == true
|
||||
|| listenData.AdditionalInfo?.OriginUrl?.ToString().Contains("youtu.be") == true)
|
||||
&& GetYoutubeId(listenData.AdditionalInfo.OriginUrl) != null)
|
||||
{
|
||||
newAlbumArt = "https://img.youtube.com/vi/" + GetYoutubeId(listenData.AdditionalInfo.OriginUrl) + "/0.jpg";
|
||||
}
|
||||
else if (listenData.AdditionalInfo?.ReleaseId != null)
|
||||
{
|
||||
newAlbumArt = "https://coverartarchive.org/release/" + listenData.AdditionalInfo?.ReleaseId + "/front-250.jpg";
|
||||
}
|
||||
else if (listenData.Release != null)
|
||||
{
|
||||
var release = FindMusicBrainzRelease(listenData.Release);
|
||||
newAlbumArt = "https://coverartarchive.org/release/" + release?.Item.Id + "/front-250.jpg";
|
||||
}
|
||||
}
|
||||
|
||||
Console.WriteLine("Album art URL: " + (newAlbumArt ?? "(none)"));
|
||||
albumArtUrl = newAlbumArt ?? "";
|
||||
}
|
||||
else
|
||||
{
|
||||
albumArtUrl = "";
|
||||
}
|
||||
|
||||
client.SetPresence(new RichPresence()
|
||||
{
|
||||
Details = $"{listenData.Name}",
|
||||
State = listenData.Artist,
|
||||
Buttons = buttons.ToArray(),
|
||||
Assets = new Assets()
|
||||
{
|
||||
SmallImageKey = "play",
|
||||
LargeImageKey = albumArtUrl?.Length > 0 ? albumArtUrl : null,
|
||||
LargeImageText = $"Listening to {listenData.Name} by {listenData.Artist}{(listenData.AdditionalInfo?.MediaPlayer != null ? " (via " + listenData.AdditionalInfo.MediaPlayer + ")" : "")}"
|
||||
}
|
||||
});
|
||||
RichPresence? presence = null;
|
||||
HandleNewListenData(listenData, out presence, config_data);
|
||||
|
||||
if (presence != null)
|
||||
client.SetPresence(presence);
|
||||
}
|
||||
else if (listenData == null)
|
||||
{
|
||||
|
@ -250,6 +146,188 @@ public class LbzRpcService
|
|||
}
|
||||
}
|
||||
|
||||
private void HandleNewListenData(ITrackInfo listenData, out RichPresence? presence, IniData config_data)
|
||||
{
|
||||
if (listenData == null || config_data == null)
|
||||
{
|
||||
presence = null;
|
||||
return;
|
||||
}
|
||||
|
||||
var buttons = new List<Button>();
|
||||
var username = config_data["general"]["listenbrainz_username"];
|
||||
var ignoredPlayers = config_data["general"]["ignored_sources"].Split(",", StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
|
||||
var prioritizeMusicBrainz = config_data["general"]["prioritise_musicbrainz"];
|
||||
|
||||
if (listenData.AdditionalInfo.OriginUrl != null
|
||||
&& (listenData.AdditionalInfo.OriginUrl?.Host == "music.youtube.com" || listenData.AdditionalInfo.OriginUrl?.Host == "www.youtube.com")
|
||||
&& GetYoutubeId(listenData.AdditionalInfo.OriginUrl) != null
|
||||
&& lastRecording != GetYoutubeId(listenData.AdditionalInfo.OriginUrl))
|
||||
{
|
||||
lastRecording = GetYoutubeId(listenData.AdditionalInfo.OriginUrl);
|
||||
|
||||
Console.WriteLine("Searching for release {0} on MusicBrainz", listenData.Release);
|
||||
Query q = new("LBZ-DRPC", new Version(1, 0, 0));
|
||||
ISearchResult<IRelease>? release = null;
|
||||
|
||||
if (listenData.Release != null || listenData.Artist != null)
|
||||
{
|
||||
release = q.FindReleases(listenData.Release ?? listenData.Artist, 1).Results?.FirstOrDefault();
|
||||
if (release?.Item.CoverArtArchive == null || !release.Item.CoverArtArchive.Front)
|
||||
{
|
||||
if (release?.Item.Aliases != null)
|
||||
foreach (IAlias alias in release.Item.Aliases)
|
||||
{
|
||||
if (alias.Primary == true)
|
||||
{
|
||||
var r = q.FindReleases(alias.Name, 1).Results?.FirstOrDefault();
|
||||
if (release != null && release.Item.CoverArtArchive?.Front == true)
|
||||
{
|
||||
release = r;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
lastRecording = GetYoutubeId(listenData.AdditionalInfo.OriginUrl);
|
||||
|
||||
if (release != null && TrySetAlbumArtUrl("https://coverartarchive.org/release/" + release.Item.Id + "/front-250.jpg"))
|
||||
{
|
||||
// all is well, carry on at the end of the if block
|
||||
}
|
||||
else if (GetYoutubeId(listenData.AdditionalInfo.OriginUrl) != null)
|
||||
{
|
||||
var youtubeId = GetYoutubeId(listenData.AdditionalInfo.OriginUrl);
|
||||
SetAlbumArtUrl("https://img.youtube.com/vi/" + youtubeId + "/mqdefault.jpg");
|
||||
}
|
||||
else
|
||||
{
|
||||
SetAlbumArtUrl(null);
|
||||
}
|
||||
}
|
||||
else if (lastRecording != listenData.AdditionalInfo?.RecordingId.ToString() && listenData.AdditionalInfo?.RecordingId != null) // MusicBrainz ID available
|
||||
{
|
||||
Console.WriteLine("Listening to {0} by {1}", listenData.Name, listenData.Artist);
|
||||
lastRecording = listenData.AdditionalInfo?.RecordingId.ToString();
|
||||
|
||||
buttons = [];
|
||||
|
||||
if (listenData.AdditionalInfo?.RecordingId != null)
|
||||
{
|
||||
buttons.Add(new Button() { Label = "Listen on MusicBrainz", Url = $"https://listenbrainz.org/player/?recording_mbids={listenData.AdditionalInfo?.RecordingId}" });
|
||||
}
|
||||
|
||||
buttons.Add(new Button() { Label = $"{username} on ListenBrainz", Url = $"https://listenbrainz.org/user/{username}" });
|
||||
|
||||
string? newAlbumArt = null;
|
||||
|
||||
if (prioritizeMusicBrainz == "true" && listenData.AdditionalInfo?.ReleaseId != null)
|
||||
{
|
||||
newAlbumArt = "https://coverartarchive.org/release/" + listenData.AdditionalInfo?.ReleaseId + "/front-250.jpg";
|
||||
}
|
||||
else if (config_data["general"]["prioritise_musicbrainz"] == "true" && listenData.Release != null)
|
||||
{
|
||||
var release = FindMusicBrainzRelease(listenData.Release);
|
||||
newAlbumArt = "https://coverartarchive.org/release/" + release?.Item.Id + "/front-250.jpg";
|
||||
}
|
||||
|
||||
if (newAlbumArt == null)
|
||||
{
|
||||
if ((listenData.AdditionalInfo?.OriginUrl?.ToString().Contains("youtube") == true
|
||||
|| listenData.AdditionalInfo?.OriginUrl?.ToString().Contains("youtu.be") == true)
|
||||
&& GetYoutubeId(listenData.AdditionalInfo.OriginUrl) != null)
|
||||
{
|
||||
Console.WriteLine("Using YouTube thumbnail as album art");
|
||||
newAlbumArt = "https://img.youtube.com/vi/" + GetYoutubeId(listenData.AdditionalInfo.OriginUrl) + "/0.jpg";
|
||||
}
|
||||
else if (listenData.AdditionalInfo?.ReleaseId != null)
|
||||
{
|
||||
Console.WriteLine("Using ListenBrainz release ID as album art");
|
||||
newAlbumArt = "https://coverartarchive.org/release/" + listenData.AdditionalInfo?.ReleaseId + "/front-250.jpg";
|
||||
}
|
||||
else if (listenData.Release != null)
|
||||
{
|
||||
var release = FindMusicBrainzRelease(listenData.Release);
|
||||
newAlbumArt = "https://coverartarchive.org/release/" + release?.Item.Id + "/front-250.jpg";
|
||||
}
|
||||
}
|
||||
|
||||
Console.WriteLine("Album art URL: " + (newAlbumArt ?? "(none)"));
|
||||
SetAlbumArtUrl(newAlbumArt);
|
||||
}
|
||||
|
||||
presence = new RichPresence()
|
||||
{
|
||||
Details = $"{listenData.Name}",
|
||||
State = listenData.Artist,
|
||||
Buttons = buttons.ToArray(),
|
||||
Assets = new Assets()
|
||||
{
|
||||
SmallImageKey = "play",
|
||||
LargeImageKey = albumArtUrl?.Length > 0 ? albumArtUrl : null,
|
||||
LargeImageText = $"Listening to {listenData.Name} by {listenData.Artist}{(listenData.AdditionalInfo?.MediaPlayer != null ? " (via " + listenData.AdditionalInfo.MediaPlayer + ")" : "")}"
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to download the album art from the given URL and sets it as the album art URL if successful.
|
||||
/// This ensures that the URL points to a valid image file (fails when e.g. Internet Archive returns a 404 page).
|
||||
/// </summary>
|
||||
/// <param name="url"></param>
|
||||
/// <returns></returns>
|
||||
private bool TrySetAlbumArtUrl(string url)
|
||||
{
|
||||
if (url == null)
|
||||
{
|
||||
SetAlbumArtUrl(null);
|
||||
return true;
|
||||
}
|
||||
|
||||
Console.WriteLine("Validating album art URL {0}", url ?? "(none)");
|
||||
|
||||
// check if the URL is valid
|
||||
try
|
||||
{
|
||||
var request = new HttpClient();
|
||||
request.Timeout = TimeSpan.FromSeconds(5);
|
||||
Task<HttpResponseMessage> response = request.GetAsync(url);
|
||||
|
||||
try
|
||||
{
|
||||
response.Wait();
|
||||
}
|
||||
catch (AggregateException) // TaskCanceledException
|
||||
{
|
||||
// Request timed out
|
||||
return false;
|
||||
}
|
||||
|
||||
if (response.Result.StatusCode == HttpStatusCode.OK)
|
||||
{
|
||||
SetAlbumArtUrl(url);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (WebException)
|
||||
{
|
||||
// URL is invalid
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void SetAlbumArtUrl(string? url)
|
||||
{
|
||||
if (url != albumArtUrl)
|
||||
{
|
||||
Console.WriteLine("Setting album art URL to {0}", url ?? "(none)");
|
||||
albumArtUrl = url ?? "";
|
||||
}
|
||||
}
|
||||
|
||||
private ISearchResult<IRelease>? FindMusicBrainzRelease(string release)
|
||||
{
|
||||
Console.WriteLine("Searching for release {0} on MusicBrainz", release);
|
||||
|
|
Loading…
Reference in New Issue