Fix playback progress sync

This commit is contained in:
Shadowghost 2022-04-25 13:40:38 +02:00
parent b740dbb21e
commit dbf0a55657
5 changed files with 65 additions and 68 deletions

View File

@ -639,7 +639,7 @@ public class TraktApi
/// <returns>Task{List{DataContracts.Users.Playback.TraktMoviePaused}}.</returns>
public async Task<List<DataContracts.Users.Playback.TraktMoviePaused>> SendGetAllPausedMoviesRequest(TraktUser traktUser)
{
return await GetFromTrakt<List<DataContracts.Users.Playback.TraktMoviePaused>>(TraktUris.PausedMovies, traktUser).ConfigureAwait(false);
return await GetFromTrakt<List<DataContracts.Users.Playback.TraktMoviePaused>>(TraktUris.PausedMovies + "?" + Random.Shared.NextInt64(), traktUser).ConfigureAwait(false);
}
/// <summary>
@ -649,7 +649,7 @@ public class TraktApi
/// <returns>Task{List{DataContracts.Users.Playback.TraktEpisodePaused}}.</returns>
public async Task<List<DataContracts.Users.Playback.TraktEpisodePaused>> SendGetPausedEpisodesRequest(TraktUser traktUser)
{
return await GetFromTrakt<List<DataContracts.Users.Playback.TraktEpisodePaused>>(TraktUris.PausedEpisodes, traktUser).ConfigureAwait(false);
return await GetFromTrakt<List<DataContracts.Users.Playback.TraktEpisodePaused>>(TraktUris.PausedEpisodes + "?" + Random.Shared.NextInt64(), traktUser).ConfigureAwait(false);
}
/// <summary>

View File

@ -93,12 +93,12 @@ public static class TraktUris
/// <summary>
/// The paused movies URI.
/// </summary>
public const string PausedMovies = BaseUrl + "/sync/playback/movies";
public const string PausedMovies = BaseUrl + "/sync/playback/movies?start_at=2000-01-01T00:00:00.000Z";
/// <summary>
/// The paused shows URI.
/// </summary>
public const string PausedEpisodes = BaseUrl + "/sync/playback/episodes";
public const string PausedEpisodes = BaseUrl + "/sync/playback/episodes?start_at=2000-01-01T00:00:00.000Z";
/// <summary>
/// The collected movies URI.

View File

@ -1,5 +1,3 @@
using System;
namespace Trakt.Model;
internal class PlaybackState

View File

@ -204,7 +204,7 @@ public class SyncFromTraktTask : IScheduledTask
if (matchedWatchedMovie != null)
{
_logger.LogDebug("Movie is in watched list: \"{Name}\"", movie.Name);
_logger.LogDebug("Movie is in watched list of user {User}: {Name}", user.Username, movie.Name);
if (!traktUser.SkipWatchedImportFromTrakt)
{
@ -218,10 +218,10 @@ public class SyncFromTraktTask : IScheduledTask
if (!userData.Played)
{
// Only change LastPlayedDate if not set or the local and remote are more than 10 minutes apart
_logger.LogDebug("Marking movie as watched locally: \"{Name}\"", movie.Name);
_logger.LogDebug("Marking movie as watched for user {User} locally: {Name}", user.Username, movie.Name);
if (tLastPlayed == null && userData.LastPlayedDate == null)
{
_logger.LogDebug("Setting movie last played date locally: \"{Name}\"", movie.Name);
_logger.LogDebug("Setting movie last played date for user {User} locally: {Name}", user.Username, movie.Name);
userData.LastPlayedDate = DateTime.Now;
}
@ -230,7 +230,7 @@ public class SyncFromTraktTask : IScheduledTask
&& (tLastPlayed.Value - userData.LastPlayedDate.Value).Duration() > TimeSpan.FromMinutes(10)
&& userData.LastPlayedDate < tLastPlayed)
{
_logger.LogDebug("Setting movie last played date locally: \"{Name}\"", movie.Name);
_logger.LogDebug("Setting movie last played date for user {User} locally: {Name}", user.Username, movie.Name);
userData.LastPlayedDate = tLastPlayed;
}
@ -241,7 +241,7 @@ public class SyncFromTraktTask : IScheduledTask
// Keep the highest play count
if (userData.PlayCount < matchedWatchedMovie.Plays)
{
_logger.LogDebug("Adjusting movie play count locally: \"{Name}\"", movie.Name);
_logger.LogDebug("Adjusting movie play count for user {User} locally: {Name}", user.Username, movie.Name);
userData.PlayCount = matchedWatchedMovie.Plays;
changed = true;
}
@ -249,7 +249,7 @@ public class SyncFromTraktTask : IScheduledTask
// Update last played if remote time is more recent
if (tLastPlayed != null && userData.LastPlayedDate < tLastPlayed)
{
_logger.LogDebug("Adjusting movie last played date locally: \"{Name}\"", movie.Name);
_logger.LogDebug("Adjusting movie last played date for user {User} locally: {Name}", user.Username, movie.Name);
userData.LastPlayedDate = tLastPlayed;
changed = true;
}
@ -257,12 +257,12 @@ public class SyncFromTraktTask : IScheduledTask
}
else if (!traktUser.SkipUnwatchedImportFromTrakt)
{
_logger.LogDebug("Movie is not in watched list: \"{Name}\"", movie.Name);
_logger.LogDebug("Movie is not in watched list: {Name}", movie.Name);
// Set movie as unwatched
if (userData.Played)
{
_logger.LogDebug("Marking movie as unwatched locally: \"{Name}\"", movie.Name);
_logger.LogDebug("Marking movie as unwatched for user {User} locally: {Name}", user.Username, movie.Name);
userData.Played = false;
changed = true;
}
@ -270,27 +270,26 @@ public class SyncFromTraktTask : IScheduledTask
if (!traktUser.SkipPlaybackProgressImportFromTrakt && matchedPausedMovie != null)
{
_logger.LogDebug("Movie is in paused list: \"{Name}\"", movie.Name);
_logger.LogDebug("Movie is in paused list of user {User}: {Name}", user.Username, movie.Name);
var lastPlayed = userData.LastPlayedDate;
DateTime? paused = null;
if (DateTime.TryParse(matchedPausedMovie.PausedAt, out var value))
{
paused = value;
}
if (paused != null && userData.LastPlayedDate < paused)
if (lastPlayed == null || (paused != null && lastPlayed < paused))
{
var currentPlaybackTicks = userData.PlaybackPositionTicks;
_logger.LogDebug("Setting playback progress of movie for user {User} locally to {Progress}%: {Data}", user.Username, matchedPausedMovie.Progress, movie.Name);
var runtimeTicks = movie.GetRunTimeTicksForPlayState();
var traktPlaybackTicks = runtimeTicks != 0
? (long)matchedPausedMovie.Progress * runtimeTicks
? (long)matchedPausedMovie.Progress * runtimeTicks / 100L
: 0;
if (traktPlaybackTicks > currentPlaybackTicks)
{
_logger.LogDebug("Setting playback progress for movie locally: \"{Name}\"", movie.Name);
userData.PlaybackPositionTicks = traktPlaybackTicks;
changed = true;
}
userData.PlaybackPositionTicks = traktPlaybackTicks;
changed = true;
}
}
@ -348,7 +347,7 @@ public class SyncFromTraktTask : IScheduledTask
if (matchedWatchedEpisode != null)
{
_logger.LogDebug("Episode is in watched list: {Data}", GetVerboseEpisodeData(episode));
_logger.LogDebug("Episode is in watched list of user {User}: {Data}", user.Username, GetVerboseEpisodeData(episode));
episodeWatched = true;
DateTime? tLastPlayed = null;
@ -361,10 +360,10 @@ public class SyncFromTraktTask : IScheduledTask
if (!userData.Played)
{
// Only change LastPlayedDate if not set or the local and remote are more than 10 minutes apart
_logger.LogDebug("Marking episode as watched locally: {Data}", GetVerboseEpisodeData(episode));
_logger.LogDebug("Marking episode as watched for user {User} locally: {Data}", user.Username, GetVerboseEpisodeData(episode));
if (tLastPlayed == null && userData.LastPlayedDate == null)
{
_logger.LogDebug("Setting episode last played date locally: {Data}", GetVerboseEpisodeData(episode));
_logger.LogDebug("Setting episode last played date for user {User} locally: {Data}", user.Username, GetVerboseEpisodeData(episode));
userData.LastPlayedDate = DateTime.Now;
}
@ -373,7 +372,7 @@ public class SyncFromTraktTask : IScheduledTask
&& (tLastPlayed.Value - userData.LastPlayedDate.Value).Duration() > TimeSpan.FromMinutes(10)
&& userData.LastPlayedDate < tLastPlayed)
{
_logger.LogDebug("Setting episode last played date locally: {Data}", GetVerboseEpisodeData(episode));
_logger.LogDebug("Setting episode last played date for user {User} locally: {Data}", user.Username, GetVerboseEpisodeData(episode));
userData.LastPlayedDate = tLastPlayed;
}
@ -384,7 +383,7 @@ public class SyncFromTraktTask : IScheduledTask
// Keep the highest play count
if (userData.PlayCount < matchedWatchedEpisode.Plays)
{
_logger.LogDebug("Adjusting episode playcount locally: {Data}", GetVerboseEpisodeData(episode));
_logger.LogDebug("Adjusting episode playcount for user {User} locally: {Data}", user.Username, GetVerboseEpisodeData(episode));
userData.PlayCount = matchedWatchedEpisode.Plays;
changed = true;
}
@ -392,20 +391,20 @@ public class SyncFromTraktTask : IScheduledTask
}
else
{
_logger.LogDebug("No season data found for {Data}", GetVerboseEpisodeData(episode));
_logger.LogDebug("No season data found for user {User} for {Data}", user.Username, GetVerboseEpisodeData(episode));
}
}
else
{
_logger.LogDebug("No show data found for {Data}", GetVerboseEpisodeData(episode));
_logger.LogDebug("No show data found for user {User} for {Data}", user.Username, GetVerboseEpisodeData(episode));
}
if (!traktUser.SkipUnwatchedImportFromTrakt && !episodeWatched)
{
_logger.LogDebug("Episode not in watched list: {Data}", GetVerboseEpisodeData(episode));
_logger.LogDebug("Episode not in watched list of user {User}: {Data}", user.Username, GetVerboseEpisodeData(episode));
if (userData.Played)
{
_logger.LogDebug("Marking episode as unwatched locally: {Data}", GetVerboseEpisodeData(episode));
_logger.LogDebug("Marking episode as unwatched for user {User} locally: {Data}", user.Username, GetVerboseEpisodeData(episode));
userData.Played = false;
changed = true;
}
@ -413,29 +412,26 @@ public class SyncFromTraktTask : IScheduledTask
if (!traktUser.SkipPlaybackProgressImportFromTrakt && matchedPausedEpisode != null)
{
_logger.LogDebug("Episode is in paused list: {Data}", GetVerboseEpisodeData(episode));
_logger.LogDebug("{Data}", matchedPausedEpisode.Episode.Title);
_logger.LogDebug("Episode is in paused list of user {User}: {Data}", user.Username, GetVerboseEpisodeData(episode));
var lastPlayed = userData.LastPlayedDate;
DateTime? paused = null;
if (DateTime.TryParse(matchedPausedEpisode.PausedAt, out var value))
{
paused = value;
}
if (paused != null && userData.LastPlayedDate < paused)
if (lastPlayed == null || (paused != null && lastPlayed < paused))
{
var currentPlaybackTicks = userData.PlaybackPositionTicks;
_logger.LogDebug("Setting playback progress of episode for user {User} locally to {Progress}%: {Data}", user.Username, matchedPausedEpisode.Progress, GetVerboseEpisodeData(episode));
var runtimeTicks = episode.GetRunTimeTicksForPlayState();
var traktPlaybackTicks = runtimeTicks != 0
? (long)matchedPausedEpisode.Progress * runtimeTicks
? (long)matchedPausedEpisode.Progress * runtimeTicks / 100L
: 0;
if (traktPlaybackTicks > currentPlaybackTicks)
{
_logger.LogDebug("Setting playback progress for episode locally: {Data}", GetVerboseEpisodeData(episode));
userData.PlaybackPositionTicks = traktPlaybackTicks;
changed = true;
}
userData.PlaybackPositionTicks = traktPlaybackTicks;
changed = true;
}
}

View File

@ -31,7 +31,6 @@ public class ServerMediator : IServerEntryPoint, IDisposable
private readonly UserDataManagerEventsHelper _userDataManagerEventsHelper;
private readonly LibraryManagerEventsHelper _libraryManagerEventsHelper;
private readonly TraktApi _traktApi;
private Dictionary<string, PlaybackState> _playbackState;
/// <summary>
@ -313,8 +312,9 @@ public class ServerMediator : IServerEntryPoint, IDisposable
}
var video = playbackProgressEventArgs.Item as Video;
var playbackPositionTicks = playbackProgressEventArgs.PlaybackPositionTicks;
var progressPercent = video.RunTimeTicks.HasValue && video.RunTimeTicks != 0 ?
(float)(playbackProgressEventArgs.PlaybackPositionTicks ?? 0) / video.RunTimeTicks.Value * 100.0f : 0.0f;
(float)(playbackPositionTicks ?? 0) / video.RunTimeTicks.Value * 100.0f : 0.0f;
_logger.LogDebug("User {User} progressed watching item {Item}.", user.Username, playbackProgressEventArgs.Item.Path);
@ -322,31 +322,34 @@ public class ServerMediator : IServerEntryPoint, IDisposable
{
if (playbackProgressEventArgs.IsPaused)
{
_logger.LogDebug("Playback paused");
if (video is Movie movie)
if (!_playbackState[traktUser.LinkedMbUserId].IsPaused)
{
_logger.LogDebug("Sending movie playback status update to trakt.tv for user {User}.", user.Username);
await _traktApi.SendMovieStatusUpdateAsync(
movie,
MediaStatus.Paused,
traktUser,
progressPercent).ConfigureAwait(false);
_logger.LogDebug("Playback paused");
_playbackState[traktUser.LinkedMbUserId].PlaybackProgress = playbackProgressEventArgs.PlaybackPositionTicks ?? 0L;
_playbackState[traktUser.LinkedMbUserId].IsPaused = true;
}
else if (video is Episode episode)
{
_logger.LogDebug("Sending episode playback status update to trakt.tv for user {User}.", user.Username);
await _traktApi.SendEpisodeStatusUpdateAsync(
episode,
MediaStatus.Paused,
traktUser,
progressPercent).ConfigureAwait(false);
if (video is Movie movie)
{
_logger.LogDebug("Sending movie playback status update to trakt.tv for user {User}.", user.Username);
await _traktApi.SendMovieStatusUpdateAsync(
movie,
MediaStatus.Paused,
traktUser,
progressPercent).ConfigureAwait(false);
_playbackState[traktUser.LinkedMbUserId].PlaybackProgress = playbackProgressEventArgs.PlaybackPositionTicks ?? 0L;
_playbackState[traktUser.LinkedMbUserId].IsPaused = false;
_playbackState[traktUser.LinkedMbUserId].PlaybackProgress = playbackProgressEventArgs.PlaybackPositionTicks ?? 0L;
_playbackState[traktUser.LinkedMbUserId].IsPaused = true;
}
else if (video is Episode episode)
{
_logger.LogDebug("Sending episode playback status update to trakt.tv for user {User}.", user.Username);
await _traktApi.SendEpisodeStatusUpdateAsync(
episode,
MediaStatus.Paused,
traktUser,
progressPercent).ConfigureAwait(false);
_playbackState[traktUser.LinkedMbUserId].PlaybackProgress = playbackProgressEventArgs.PlaybackPositionTicks ?? 0L;
_playbackState[traktUser.LinkedMbUserId].IsPaused = true;
}
}
}
else