add to apple timeline with stored offset check
This commit is contained in:
parent
7e8a9d1e29
commit
bfc7a0db34
Selector.AppleMusic
@ -26,15 +26,19 @@ public class AppleMusicApi(HttpClient client, string developerToken, string user
|
||||
{
|
||||
if (response.StatusCode == HttpStatusCode.Unauthorized)
|
||||
{
|
||||
throw new UnauthorisedException();
|
||||
throw new UnauthorisedException { StatusCode = response.StatusCode };
|
||||
}
|
||||
else if (response.StatusCode == HttpStatusCode.Forbidden)
|
||||
{
|
||||
throw new ForbiddenException();
|
||||
throw new ForbiddenException { StatusCode = response.StatusCode };
|
||||
}
|
||||
else if (response.StatusCode == HttpStatusCode.TooManyRequests)
|
||||
{
|
||||
throw new RateLimitException();
|
||||
throw new RateLimitException { StatusCode = response.StatusCode };
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new AppleMusicException { StatusCode = response.StatusCode };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -37,50 +37,20 @@ public class AppleTimeline : Timeline<AppleMusicCurrentlyPlayingContext>
|
||||
return newItems;
|
||||
}
|
||||
|
||||
var stop = false;
|
||||
var found = 0;
|
||||
var startIdx = 0;
|
||||
while (!stop)
|
||||
var (found, startIdx) = Loop(items, 0);
|
||||
|
||||
TimelineItem<AppleMusicCurrentlyPlayingContext>? popped = null;
|
||||
if (found == 0)
|
||||
{
|
||||
for (var i = 0; i < items.Count; i++)
|
||||
var (foundOffseted, startIdxOffseted) = Loop(items, 1);
|
||||
|
||||
if (foundOffseted > found)
|
||||
{
|
||||
var storedIdx = (Recent.Count - 1) - i;
|
||||
// start from the end, minus this loops index, minus the offset
|
||||
var pulledIdx = (items.Count - 1) - i - startIdx;
|
||||
popped = Recent[^1];
|
||||
Recent.RemoveAt(Recent.Count - 1);
|
||||
|
||||
if (pulledIdx < 0)
|
||||
{
|
||||
// ran to the end of new items and none matched the end, add all the new ones
|
||||
stop = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (storedIdx < 0)
|
||||
{
|
||||
// all the new stuff matches, we're done and there's nothing new to add
|
||||
stop = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (Recent[storedIdx].Item.Track.Id == items[pulledIdx].Track.Id)
|
||||
{
|
||||
// good, keep going
|
||||
found++;
|
||||
if (found >= 3)
|
||||
{
|
||||
stop = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// bad, doesn't match, break and bump stored
|
||||
found = 0;
|
||||
break;
|
||||
}
|
||||
startIdx = startIdxOffseted;
|
||||
}
|
||||
|
||||
if (!stop) startIdx += 1;
|
||||
}
|
||||
|
||||
foreach (var item in items.TakeLast(startIdx))
|
||||
@ -89,6 +59,77 @@ public class AppleTimeline : Timeline<AppleMusicCurrentlyPlayingContext>
|
||||
Recent.Add(TimelineItem<AppleMusicCurrentlyPlayingContext>.From(item, DateTime.UtcNow));
|
||||
}
|
||||
|
||||
if (popped is not null)
|
||||
{
|
||||
var idx = Recent.FindIndex(x => x.Item.Track.Id == popped.Item.Track.Id);
|
||||
if (idx >= 0)
|
||||
{
|
||||
newItems.RemoveAt(idx);
|
||||
}
|
||||
}
|
||||
|
||||
CheckSize();
|
||||
|
||||
return newItems;
|
||||
}
|
||||
|
||||
private (int, int) Loop(List<AppleMusicCurrentlyPlayingContext> items, int storedOffset)
|
||||
{
|
||||
var stop = false;
|
||||
var found = 0;
|
||||
var startIdx = 0;
|
||||
while (!stop)
|
||||
{
|
||||
found = Loop(items, storedOffset, ref startIdx, ref stop);
|
||||
|
||||
if (!stop) startIdx += 1;
|
||||
}
|
||||
|
||||
return (found, startIdx);
|
||||
}
|
||||
|
||||
private int Loop(List<AppleMusicCurrentlyPlayingContext> items, int storedOffset, ref int startIdx, ref bool stop)
|
||||
{
|
||||
var found = 0;
|
||||
|
||||
for (var i = 0; i < items.Count; i++)
|
||||
{
|
||||
var storedIdx = (Recent.Count - 1) - i - storedOffset;
|
||||
// start from the end, minus this loops index, minus the offset
|
||||
var pulledIdx = (items.Count - 1) - i - startIdx;
|
||||
|
||||
if (pulledIdx < 0)
|
||||
{
|
||||
// ran to the end of new items and none matched the end, add all the new ones
|
||||
stop = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (storedIdx < 0)
|
||||
{
|
||||
// all the new stuff matches, we're done and there's nothing new to add
|
||||
stop = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (Recent[storedIdx].Item.Track.Id == items[pulledIdx].Track.Id)
|
||||
{
|
||||
// good, keep going
|
||||
found++;
|
||||
if (found >= 3)
|
||||
{
|
||||
stop = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// bad, doesn't match, break and bump stored
|
||||
found = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
}
|
@ -1,5 +1,8 @@
|
||||
using System.Net;
|
||||
|
||||
namespace Selector.AppleMusic.Exceptions;
|
||||
|
||||
public class AppleMusicException : Exception
|
||||
{
|
||||
public HttpStatusCode StatusCode { get; set; }
|
||||
}
|
@ -7,7 +7,7 @@ namespace Selector.AppleMusic.Watcher;
|
||||
|
||||
public class AppleMusicPlayerWatcher : BaseWatcher, IAppleMusicPlayerWatcher
|
||||
{
|
||||
new protected readonly ILogger<AppleMusicPlayerWatcher> Logger;
|
||||
private new readonly ILogger<AppleMusicPlayerWatcher> Logger;
|
||||
private readonly AppleMusicApi _appleMusicApi;
|
||||
|
||||
public event EventHandler<AppleListeningChangeEventArgs> NetworkPoll;
|
||||
@ -15,12 +15,12 @@ public class AppleMusicPlayerWatcher : BaseWatcher, IAppleMusicPlayerWatcher
|
||||
public event EventHandler<AppleListeningChangeEventArgs> AlbumChange;
|
||||
public event EventHandler<AppleListeningChangeEventArgs> ArtistChange;
|
||||
|
||||
public AppleMusicCurrentlyPlayingContext Live { get; protected set; }
|
||||
protected AppleMusicCurrentlyPlayingContext Previous { get; set; }
|
||||
public AppleTimeline Past { get; set; } = new();
|
||||
public AppleMusicCurrentlyPlayingContext? Live { get; private set; }
|
||||
private AppleMusicCurrentlyPlayingContext? Previous { get; set; }
|
||||
public AppleTimeline Past { get; private set; } = new();
|
||||
|
||||
public AppleMusicPlayerWatcher(AppleMusicApi appleMusicClient,
|
||||
ILogger<AppleMusicPlayerWatcher> logger = null,
|
||||
ILogger<AppleMusicPlayerWatcher>? logger = null,
|
||||
int pollPeriod = 3000
|
||||
) : base(logger)
|
||||
{
|
||||
@ -35,10 +35,22 @@ public class AppleMusicPlayerWatcher : BaseWatcher, IAppleMusicPlayerWatcher
|
||||
|
||||
try
|
||||
{
|
||||
using var polledLogScope = Logger.BeginScope(new Dictionary<string, object>() { { "user_id", Id } });
|
||||
|
||||
Logger.LogTrace("Making Apple Music call");
|
||||
var polledCurrent = await _appleMusicApi.GetRecentlyPlayedTracks();
|
||||
|
||||
// using var polledLogScope = Logger.BeginScope(new Dictionary<string, object>() { { "context", polledCurrent?.DisplayString() } });
|
||||
if (polledCurrent is null)
|
||||
{
|
||||
Logger.LogInformation("Null response when calling Apple Music API");
|
||||
return;
|
||||
}
|
||||
|
||||
if (polledCurrent.Data is null)
|
||||
{
|
||||
Logger.LogInformation("Null track list when calling Apple Music API");
|
||||
return;
|
||||
}
|
||||
|
||||
Logger.LogTrace("Received Apple Music call");
|
||||
|
||||
@ -65,23 +77,28 @@ public class AppleMusicPlayerWatcher : BaseWatcher, IAppleMusicPlayerWatcher
|
||||
}
|
||||
catch (RateLimitException e)
|
||||
{
|
||||
Logger.LogDebug("Rate Limit exception: [{message}]", e.Message);
|
||||
// throw e;
|
||||
Logger.LogError(e, "Rate Limit exception");
|
||||
// throw;
|
||||
}
|
||||
catch (ForbiddenException e)
|
||||
{
|
||||
Logger.LogDebug("Forbidden exception: [{message}]", e.Message);
|
||||
throw;
|
||||
Logger.LogError(e, "Forbidden exception");
|
||||
// throw;
|
||||
}
|
||||
catch (ServiceException e)
|
||||
{
|
||||
Logger.LogDebug("Apple Music internal error: [{message}]", e.Message);
|
||||
// throw e;
|
||||
Logger.LogInformation("Apple Music internal error");
|
||||
// throw;
|
||||
}
|
||||
catch (UnauthorisedException e)
|
||||
{
|
||||
Logger.LogDebug("Unauthorised exception: [{message}]", e.Message);
|
||||
// throw e;
|
||||
Logger.LogError(e, "Unauthorised exception");
|
||||
// throw;
|
||||
}
|
||||
catch (AppleMusicException e)
|
||||
{
|
||||
Logger.LogInformation("Apple Music exception ({})", e.StatusCode);
|
||||
// throw;
|
||||
}
|
||||
}
|
||||
|
||||
@ -89,7 +106,7 @@ public class AppleMusicPlayerWatcher : BaseWatcher, IAppleMusicPlayerWatcher
|
||||
{
|
||||
var lastTrack = recentlyPlayedTracks.Data?.FirstOrDefault();
|
||||
|
||||
if (Live != null && Live.Track != null && Live.Track.Id == lastTrack?.Id)
|
||||
if (Live is { Track: not null } && Live.Track.Id == lastTrack?.Id)
|
||||
{
|
||||
Live = new()
|
||||
{
|
||||
@ -116,27 +133,27 @@ public class AppleMusicPlayerWatcher : BaseWatcher, IAppleMusicPlayerWatcher
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
protected AppleListeningChangeEventArgs GetEvent() =>
|
||||
private AppleListeningChangeEventArgs GetEvent() =>
|
||||
AppleListeningChangeEventArgs.From(Previous, Live, Past, id: Id);
|
||||
|
||||
#region Event Firers
|
||||
|
||||
protected virtual void OnNetworkPoll(AppleListeningChangeEventArgs args)
|
||||
private void OnNetworkPoll(AppleListeningChangeEventArgs args)
|
||||
{
|
||||
NetworkPoll?.Invoke(this, args);
|
||||
}
|
||||
|
||||
protected virtual void OnItemChange(AppleListeningChangeEventArgs args)
|
||||
private void OnItemChange(AppleListeningChangeEventArgs args)
|
||||
{
|
||||
ItemChange?.Invoke(this, args);
|
||||
}
|
||||
|
||||
protected virtual void OnAlbumChange(AppleListeningChangeEventArgs args)
|
||||
protected void OnAlbumChange(AppleListeningChangeEventArgs args)
|
||||
{
|
||||
AlbumChange?.Invoke(this, args);
|
||||
}
|
||||
|
||||
protected virtual void OnArtistChange(AppleListeningChangeEventArgs args)
|
||||
protected void OnArtistChange(AppleListeningChangeEventArgs args)
|
||||
{
|
||||
ArtistChange?.Invoke(this, args);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user