parent
041dc659fe
commit
d09e5d8eb4
|
@ -1,22 +1,28 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using FluentValidation.Results;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Common.Http;
|
||||
using NzbDrone.Core.MediaFiles;
|
||||
using NzbDrone.Core.MediaFiles.MediaInfo;
|
||||
using NzbDrone.Core.Notifications.Trakt.Resource;
|
||||
using NzbDrone.Core.Qualities;
|
||||
using NzbDrone.Core.Tv;
|
||||
using NzbDrone.Core.Validation;
|
||||
|
||||
namespace NzbDrone.Core.Notifications.Trakt
|
||||
{
|
||||
public class Trakt : NotificationBase<TraktSettings>
|
||||
{
|
||||
private readonly ITraktService _traktService;
|
||||
private readonly ITraktProxy _proxy;
|
||||
private readonly INotificationRepository _notificationRepository;
|
||||
private readonly Logger _logger;
|
||||
|
||||
public Trakt(ITraktService traktService, INotificationRepository notificationRepository, Logger logger)
|
||||
public Trakt(ITraktProxy proxy, INotificationRepository notificationRepository, Logger logger)
|
||||
{
|
||||
_traktService = traktService;
|
||||
_proxy = proxy;
|
||||
_notificationRepository = notificationRepository;
|
||||
_logger = logger;
|
||||
}
|
||||
|
@ -26,24 +32,53 @@ namespace NzbDrone.Core.Notifications.Trakt
|
|||
|
||||
public override void OnDownload(DownloadMessage message)
|
||||
{
|
||||
_traktService.AddEpisodeToCollection(Settings, message.Series, message.EpisodeFile);
|
||||
RefreshTokenIfNecessary();
|
||||
AddEpisodeToCollection(Settings, message.Series, message.EpisodeFile);
|
||||
}
|
||||
|
||||
public override void OnEpisodeFileDelete(EpisodeDeleteMessage deleteMessage)
|
||||
{
|
||||
_traktService.RemoveEpisodeFromCollection(Settings, deleteMessage.Series, deleteMessage.EpisodeFile);
|
||||
RefreshTokenIfNecessary();
|
||||
RemoveEpisodeFromCollection(Settings, deleteMessage.Series, deleteMessage.EpisodeFile);
|
||||
}
|
||||
|
||||
public override void OnSeriesDelete(SeriesDeleteMessage deleteMessage)
|
||||
{
|
||||
_traktService.RemoveSeriesFromCollection(Settings, deleteMessage.Series);
|
||||
RefreshTokenIfNecessary();
|
||||
RemoveSeriesFromCollection(Settings, deleteMessage.Series);
|
||||
}
|
||||
|
||||
public override ValidationResult Test()
|
||||
{
|
||||
var failures = new List<ValidationFailure>();
|
||||
|
||||
failures.AddIfNotNull(_traktService.Test(Settings));
|
||||
RefreshTokenIfNecessary();
|
||||
|
||||
try
|
||||
{
|
||||
_proxy.GetUserName(Settings.AccessToken);
|
||||
}
|
||||
catch (HttpException ex)
|
||||
{
|
||||
if (ex.Response.StatusCode == HttpStatusCode.Unauthorized)
|
||||
{
|
||||
_logger.Error(ex, "Access Token is invalid: " + ex.Message);
|
||||
|
||||
failures.Add(new ValidationFailure("Token", "Access Token is invalid"));
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Error(ex, "Unable to send test message: " + ex.Message);
|
||||
|
||||
failures.Add(new ValidationFailure("Token", "Unable to send test message"));
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex, "Unable to send test message: " + ex.Message);
|
||||
|
||||
failures.Add(new ValidationFailure("", "Unable to send test message"));
|
||||
}
|
||||
|
||||
return new ValidationResult(failures);
|
||||
}
|
||||
|
@ -52,7 +87,7 @@ namespace NzbDrone.Core.Notifications.Trakt
|
|||
{
|
||||
if (action == "startOAuth")
|
||||
{
|
||||
var request = _traktService.GetOAuthRequest(query["callbackUrl"]);
|
||||
var request = _proxy.GetOAuthRequest(query["callbackUrl"]);
|
||||
|
||||
return new
|
||||
{
|
||||
|
@ -66,14 +101,22 @@ namespace NzbDrone.Core.Notifications.Trakt
|
|||
accessToken = query["access_token"],
|
||||
expires = DateTime.UtcNow.AddSeconds(int.Parse(query["expires_in"])),
|
||||
refreshToken = query["refresh_token"],
|
||||
authUser = _traktService.GetUserName(query["access_token"])
|
||||
authUser = _proxy.GetUserName(query["access_token"])
|
||||
};
|
||||
}
|
||||
|
||||
return new { };
|
||||
}
|
||||
|
||||
public void RefreshToken()
|
||||
private void RefreshTokenIfNecessary()
|
||||
{
|
||||
if (Settings.Expires < DateTime.UtcNow.AddMinutes(5))
|
||||
{
|
||||
RefreshToken();
|
||||
}
|
||||
}
|
||||
|
||||
private void RefreshToken()
|
||||
{
|
||||
_logger.Trace("Refreshing Token");
|
||||
|
||||
|
@ -81,11 +124,12 @@ namespace NzbDrone.Core.Notifications.Trakt
|
|||
|
||||
try
|
||||
{
|
||||
var response = _traktService.RefreshAuthToken(Settings.RefreshToken);
|
||||
var response = _proxy.RefreshAuthToken(Settings.RefreshToken);
|
||||
|
||||
if (response != null)
|
||||
{
|
||||
var token = response;
|
||||
|
||||
Settings.AccessToken = token.AccessToken;
|
||||
Settings.Expires = DateTime.UtcNow.AddSeconds(token.ExpiresIn);
|
||||
Settings.RefreshToken = token.RefreshToken ?? Settings.RefreshToken;
|
||||
|
@ -96,10 +140,246 @@ namespace NzbDrone.Core.Notifications.Trakt
|
|||
}
|
||||
}
|
||||
}
|
||||
catch (HttpException)
|
||||
catch (HttpException ex)
|
||||
{
|
||||
_logger.Warn($"Error refreshing trakt access token");
|
||||
_logger.Warn(ex, "Error refreshing trakt access token");
|
||||
}
|
||||
}
|
||||
|
||||
private void AddEpisodeToCollection(TraktSettings settings, Series series, EpisodeFile episodeFile)
|
||||
{
|
||||
var payload = new TraktCollectShowsResource
|
||||
{
|
||||
Shows = new List<TraktCollectShow>()
|
||||
};
|
||||
|
||||
var traktResolution = MapResolution(episodeFile.Quality.Quality.Resolution, episodeFile.MediaInfo?.ScanType);
|
||||
var mediaType = MapMediaType(episodeFile.Quality.Quality.Source);
|
||||
var audio = MapAudio(episodeFile);
|
||||
var audioChannels = MapAudioChannels(episodeFile, audio);
|
||||
|
||||
var payloadEpisodes = new List<TraktEpisodeResource>();
|
||||
|
||||
foreach (var episode in episodeFile.Episodes.Value)
|
||||
{
|
||||
payloadEpisodes.Add(new TraktEpisodeResource
|
||||
{
|
||||
Number = episode.EpisodeNumber,
|
||||
CollectedAt = DateTime.Now,
|
||||
Resolution = traktResolution,
|
||||
MediaType = mediaType,
|
||||
AudioChannels = audioChannels,
|
||||
Audio = audio,
|
||||
});
|
||||
}
|
||||
|
||||
var payloadSeasons = new List<TraktSeasonResource>();
|
||||
payloadSeasons.Add(new TraktSeasonResource
|
||||
{
|
||||
Number = episodeFile.SeasonNumber,
|
||||
Episodes = payloadEpisodes
|
||||
});
|
||||
|
||||
payload.Shows.Add(new TraktCollectShow
|
||||
{
|
||||
Title = series.Title,
|
||||
Year = series.Year,
|
||||
Ids = new TraktShowIdsResource
|
||||
{
|
||||
Tvdb = series.TvdbId,
|
||||
Imdb = series.ImdbId ?? "",
|
||||
},
|
||||
Seasons = payloadSeasons,
|
||||
});
|
||||
|
||||
_proxy.AddToCollection(payload, settings.AccessToken);
|
||||
}
|
||||
|
||||
private void RemoveEpisodeFromCollection(TraktSettings settings, Series series, EpisodeFile episodeFile)
|
||||
{
|
||||
var payload = new TraktCollectShowsResource
|
||||
{
|
||||
Shows = new List<TraktCollectShow>()
|
||||
};
|
||||
|
||||
var payloadEpisodes = new List<TraktEpisodeResource>();
|
||||
|
||||
foreach (var episode in episodeFile.Episodes.Value)
|
||||
{
|
||||
payloadEpisodes.Add(new TraktEpisodeResource
|
||||
{
|
||||
Number = episode.EpisodeNumber
|
||||
});
|
||||
}
|
||||
|
||||
var payloadSeasons = new List<TraktSeasonResource>();
|
||||
payloadSeasons.Add(new TraktSeasonResource
|
||||
{
|
||||
Number = episodeFile.SeasonNumber,
|
||||
Episodes = payloadEpisodes
|
||||
});
|
||||
|
||||
payload.Shows.Add(new TraktCollectShow
|
||||
{
|
||||
Title = series.Title,
|
||||
Year = series.Year,
|
||||
Ids = new TraktShowIdsResource
|
||||
{
|
||||
Tvdb = series.TvdbId,
|
||||
Imdb = series.ImdbId ?? "",
|
||||
},
|
||||
Seasons = payloadSeasons,
|
||||
});
|
||||
|
||||
_proxy.RemoveFromCollection(payload, settings.AccessToken);
|
||||
}
|
||||
|
||||
private void RemoveSeriesFromCollection(TraktSettings settings, Series series)
|
||||
{
|
||||
var payload = new TraktCollectShowsResource
|
||||
{
|
||||
Shows = new List<TraktCollectShow>()
|
||||
};
|
||||
|
||||
payload.Shows.Add(new TraktCollectShow
|
||||
{
|
||||
Title = series.Title,
|
||||
Year = series.Year,
|
||||
Ids = new TraktShowIdsResource
|
||||
{
|
||||
Tvdb = series.TvdbId,
|
||||
Imdb = series.ImdbId ?? "",
|
||||
},
|
||||
});
|
||||
|
||||
_proxy.RemoveFromCollection(payload, settings.AccessToken);
|
||||
}
|
||||
|
||||
private string MapMediaType(QualitySource source)
|
||||
{
|
||||
var traktSource = string.Empty;
|
||||
|
||||
switch (source)
|
||||
{
|
||||
case QualitySource.Web:
|
||||
case QualitySource.WebRip:
|
||||
traktSource = "digital";
|
||||
break;
|
||||
case QualitySource.BlurayRaw:
|
||||
case QualitySource.Bluray:
|
||||
traktSource = "bluray";
|
||||
break;
|
||||
case QualitySource.Television:
|
||||
case QualitySource.TelevisionRaw:
|
||||
traktSource = "vhs";
|
||||
break;
|
||||
case QualitySource.DVD:
|
||||
traktSource = "dvd";
|
||||
break;
|
||||
}
|
||||
|
||||
return traktSource;
|
||||
}
|
||||
|
||||
private string MapResolution(int resolution, string scanType)
|
||||
{
|
||||
var traktResolution = string.Empty;
|
||||
|
||||
// var interlacedTypes = new string[] { "Interlaced", "MBAFF", "PAFF" };
|
||||
var scanIdentifier = scanType.IsNotNullOrWhiteSpace() && TraktInterlacedTypes.interlacedTypes.Contains(scanType) ? "i" : "p";
|
||||
|
||||
switch (resolution)
|
||||
{
|
||||
case 2160:
|
||||
traktResolution = "uhd_4k";
|
||||
break;
|
||||
case 1080:
|
||||
traktResolution = $"hd_1080{scanIdentifier}";
|
||||
break;
|
||||
case 720:
|
||||
traktResolution = "hd_720p";
|
||||
break;
|
||||
case 576:
|
||||
traktResolution = $"sd_576{scanIdentifier}";
|
||||
break;
|
||||
case 480:
|
||||
traktResolution = $"sd_480{scanIdentifier}";
|
||||
break;
|
||||
}
|
||||
|
||||
return traktResolution;
|
||||
}
|
||||
|
||||
private string MapAudio(EpisodeFile episodeFile)
|
||||
{
|
||||
var traktAudioFormat = string.Empty;
|
||||
|
||||
var audioCodec = episodeFile.MediaInfo != null ? MediaInfoFormatter.FormatAudioCodec(episodeFile.MediaInfo, episodeFile.SceneName) : string.Empty;
|
||||
|
||||
switch (audioCodec)
|
||||
{
|
||||
case "AC3":
|
||||
traktAudioFormat = "dolby_digital";
|
||||
break;
|
||||
case "EAC3":
|
||||
traktAudioFormat = "dolby_digital_plus";
|
||||
break;
|
||||
case "TrueHD":
|
||||
traktAudioFormat = "dolby_truehd";
|
||||
break;
|
||||
case "EAC3 Atmos":
|
||||
traktAudioFormat = "dolby_digital_plus_atmos";
|
||||
break;
|
||||
case "TrueHD Atmos":
|
||||
traktAudioFormat = "dolby_atmos";
|
||||
break;
|
||||
case "DTS":
|
||||
case "DTS-ES":
|
||||
traktAudioFormat = "dts";
|
||||
break;
|
||||
case "DTS-HD MA":
|
||||
traktAudioFormat = "dts_ma";
|
||||
break;
|
||||
case "DTS-HD HRA":
|
||||
traktAudioFormat = "dts_hr";
|
||||
break;
|
||||
case "DTS-X":
|
||||
traktAudioFormat = "dts_x";
|
||||
break;
|
||||
case "MP3":
|
||||
traktAudioFormat = "mp3";
|
||||
break;
|
||||
case "MP2":
|
||||
traktAudioFormat = "mp2";
|
||||
break;
|
||||
case "Vorbis":
|
||||
traktAudioFormat = "ogg";
|
||||
break;
|
||||
case "WMA":
|
||||
traktAudioFormat = "wma";
|
||||
break;
|
||||
case "AAC":
|
||||
traktAudioFormat = "aac";
|
||||
break;
|
||||
case "PCM":
|
||||
traktAudioFormat = "lpcm";
|
||||
break;
|
||||
case "FLAC":
|
||||
traktAudioFormat = "flac";
|
||||
break;
|
||||
case "Opus":
|
||||
traktAudioFormat = "ogg_opus";
|
||||
break;
|
||||
}
|
||||
|
||||
return traktAudioFormat;
|
||||
}
|
||||
|
||||
private string MapAudioChannels(EpisodeFile episodeFile, string audioFormat)
|
||||
{
|
||||
var audioChannels = episodeFile.MediaInfo != null ? MediaInfoFormatter.FormatAudioChannels(episodeFile.MediaInfo).ToString("0.0") : string.Empty;
|
||||
|
||||
return audioChannels;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,6 @@ namespace NzbDrone.Core.Notifications.Trakt
|
|||
TraktAuthRefreshResource RefreshAuthToken(string refreshToken);
|
||||
void AddToCollection(TraktCollectShowsResource payload, string accessToken);
|
||||
void RemoveFromCollection(TraktCollectShowsResource payload, string accessToken);
|
||||
HttpRequest BuildTraktRequest(string resource, HttpMethod method, string accessToken);
|
||||
}
|
||||
|
||||
public class TraktProxy : ITraktProxy
|
||||
|
@ -36,60 +35,30 @@ namespace NzbDrone.Core.Notifications.Trakt
|
|||
|
||||
public void AddToCollection(TraktCollectShowsResource payload, string accessToken)
|
||||
{
|
||||
var request = BuildTraktRequest("sync/collection", HttpMethod.Post, accessToken);
|
||||
var request = BuildRequest("sync/collection", HttpMethod.Post, accessToken);
|
||||
|
||||
request.Headers.ContentType = "application/json";
|
||||
request.SetContent(payload.ToJson());
|
||||
|
||||
try
|
||||
{
|
||||
_httpClient.Execute(request);
|
||||
}
|
||||
catch (HttpException ex)
|
||||
{
|
||||
_logger.Error(ex, "Unable to post payload {0}", payload);
|
||||
throw new TraktException("Unable to post payload", ex);
|
||||
}
|
||||
MakeRequest(request);
|
||||
}
|
||||
|
||||
public void RemoveFromCollection(TraktCollectShowsResource payload, string accessToken)
|
||||
{
|
||||
var request = BuildTraktRequest("sync/collection/remove", HttpMethod.Post, accessToken);
|
||||
var request = BuildRequest("sync/collection/remove", HttpMethod.Post, accessToken);
|
||||
|
||||
request.Headers.ContentType = "application/json";
|
||||
var temp = payload.ToJson();
|
||||
request.SetContent(payload.ToJson());
|
||||
|
||||
try
|
||||
{
|
||||
_httpClient.Execute(request);
|
||||
}
|
||||
catch (HttpException ex)
|
||||
{
|
||||
_logger.Error(ex, "Unable to post payload {0}", payload);
|
||||
throw new TraktException("Unable to post payload", ex);
|
||||
}
|
||||
MakeRequest(request);
|
||||
}
|
||||
|
||||
public string GetUserName(string accessToken)
|
||||
{
|
||||
var request = BuildTraktRequest("users/settings", HttpMethod.Get, accessToken);
|
||||
var request = BuildRequest("users/settings", HttpMethod.Get, accessToken);
|
||||
var response = _httpClient.Get<TraktUserSettingsResource>(request);
|
||||
|
||||
try
|
||||
{
|
||||
var response = _httpClient.Get<TraktUserSettingsResource>(request);
|
||||
|
||||
if (response != null && response.Resource != null)
|
||||
{
|
||||
return response.Resource.User.Ids.Slug;
|
||||
}
|
||||
}
|
||||
catch (HttpException)
|
||||
{
|
||||
_logger.Warn($"Error refreshing trakt access token");
|
||||
}
|
||||
|
||||
return null;
|
||||
return response?.Resource?.User?.Ids?.Slug;
|
||||
}
|
||||
|
||||
public HttpRequest GetOAuthRequest(string callbackUrl)
|
||||
|
@ -111,7 +80,7 @@ namespace NzbDrone.Core.Notifications.Trakt
|
|||
return _httpClient.Get<TraktAuthRefreshResource>(request)?.Resource ?? null;
|
||||
}
|
||||
|
||||
public HttpRequest BuildTraktRequest(string resource, HttpMethod method, string accessToken)
|
||||
private HttpRequest BuildRequest(string resource, HttpMethod method, string accessToken)
|
||||
{
|
||||
var request = new HttpRequestBuilder(URL).Resource(resource).Build();
|
||||
request.Method = method;
|
||||
|
@ -127,5 +96,17 @@ namespace NzbDrone.Core.Notifications.Trakt
|
|||
|
||||
return request;
|
||||
}
|
||||
|
||||
private void MakeRequest(HttpRequest request)
|
||||
{
|
||||
try
|
||||
{
|
||||
_httpClient.Execute(request);
|
||||
}
|
||||
catch (HttpException ex)
|
||||
{
|
||||
throw new TraktException("Unable to send payload", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,319 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using FluentValidation.Results;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Common.Http;
|
||||
using NzbDrone.Core.MediaFiles;
|
||||
using NzbDrone.Core.MediaFiles.MediaInfo;
|
||||
using NzbDrone.Core.Notifications.Trakt.Resource;
|
||||
using NzbDrone.Core.Qualities;
|
||||
using NzbDrone.Core.Tv;
|
||||
|
||||
namespace NzbDrone.Core.Notifications.Trakt
|
||||
{
|
||||
public interface ITraktService
|
||||
{
|
||||
HttpRequest GetOAuthRequest(string callbackUrl);
|
||||
TraktAuthRefreshResource RefreshAuthToken(string refreshToken);
|
||||
void AddEpisodeToCollection(TraktSettings settings, Series series, EpisodeFile episodeFile);
|
||||
void RemoveEpisodeFromCollection(TraktSettings settings, Series series, EpisodeFile episodeFile);
|
||||
void RemoveSeriesFromCollection(TraktSettings settings, Series series);
|
||||
string GetUserName(string accessToken);
|
||||
ValidationFailure Test(TraktSettings settings);
|
||||
}
|
||||
|
||||
public class TraktService : ITraktService
|
||||
{
|
||||
private readonly ITraktProxy _proxy;
|
||||
private readonly Logger _logger;
|
||||
|
||||
public TraktService(ITraktProxy proxy,
|
||||
Logger logger)
|
||||
{
|
||||
_proxy = proxy;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public string GetUserName(string accessToken)
|
||||
{
|
||||
return _proxy.GetUserName(accessToken);
|
||||
}
|
||||
|
||||
public HttpRequest GetOAuthRequest(string callbackUrl)
|
||||
{
|
||||
return _proxy.GetOAuthRequest(callbackUrl);
|
||||
}
|
||||
|
||||
public TraktAuthRefreshResource RefreshAuthToken(string refreshToken)
|
||||
{
|
||||
return _proxy.RefreshAuthToken(refreshToken);
|
||||
}
|
||||
|
||||
public ValidationFailure Test(TraktSettings settings)
|
||||
{
|
||||
try
|
||||
{
|
||||
GetUserName(settings.AccessToken);
|
||||
|
||||
return null;
|
||||
}
|
||||
catch (HttpException ex)
|
||||
{
|
||||
if (ex.Response.StatusCode == HttpStatusCode.Unauthorized)
|
||||
{
|
||||
_logger.Error(ex, "Access Token is invalid: " + ex.Message);
|
||||
|
||||
return new ValidationFailure("Token", "Access Token is invalid");
|
||||
}
|
||||
|
||||
_logger.Error(ex, "Unable to send test message: " + ex.Message);
|
||||
|
||||
return new ValidationFailure("Token", "Unable to send test message");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex, "Unable to send test message: " + ex.Message);
|
||||
|
||||
return new ValidationFailure("", "Unable to send test message");
|
||||
}
|
||||
}
|
||||
|
||||
public void AddEpisodeToCollection(TraktSettings settings, Series series, EpisodeFile episodeFile)
|
||||
{
|
||||
var payload = new TraktCollectShowsResource
|
||||
{
|
||||
Shows = new List<TraktCollectShow>()
|
||||
};
|
||||
|
||||
var traktResolution = MapResolution(episodeFile.Quality.Quality.Resolution, episodeFile.MediaInfo?.ScanType);
|
||||
var mediaType = MapMediaType(episodeFile.Quality.Quality.Source);
|
||||
var audio = MapAudio(episodeFile);
|
||||
var audioChannels = MapAudioChannels(episodeFile, audio);
|
||||
|
||||
var payloadEpisodes = new List<TraktEpisodeResource>();
|
||||
|
||||
foreach (var episode in episodeFile.Episodes.Value)
|
||||
{
|
||||
payloadEpisodes.Add(new TraktEpisodeResource
|
||||
{
|
||||
Number = episode.EpisodeNumber,
|
||||
CollectedAt = DateTime.Now,
|
||||
Resolution = traktResolution,
|
||||
MediaType = mediaType,
|
||||
AudioChannels = audioChannels,
|
||||
Audio = audio,
|
||||
});
|
||||
}
|
||||
|
||||
var payloadSeasons = new List<TraktSeasonResource>();
|
||||
payloadSeasons.Add(new TraktSeasonResource
|
||||
{
|
||||
Number = episodeFile.SeasonNumber,
|
||||
Episodes = payloadEpisodes
|
||||
});
|
||||
|
||||
payload.Shows.Add(new TraktCollectShow
|
||||
{
|
||||
Title = series.Title,
|
||||
Year = series.Year,
|
||||
Ids = new TraktShowIdsResource
|
||||
{
|
||||
Tvdb = series.TvdbId,
|
||||
Imdb = series.ImdbId ?? "",
|
||||
},
|
||||
Seasons = payloadSeasons,
|
||||
});
|
||||
|
||||
_proxy.AddToCollection(payload, settings.AccessToken);
|
||||
}
|
||||
|
||||
public void RemoveEpisodeFromCollection(TraktSettings settings, Series series, EpisodeFile episodeFile)
|
||||
{
|
||||
var payload = new TraktCollectShowsResource
|
||||
{
|
||||
Shows = new List<TraktCollectShow>()
|
||||
};
|
||||
|
||||
var payloadEpisodes = new List<TraktEpisodeResource>();
|
||||
|
||||
foreach (var episode in episodeFile.Episodes.Value)
|
||||
{
|
||||
payloadEpisodes.Add(new TraktEpisodeResource
|
||||
{
|
||||
Number = episode.EpisodeNumber
|
||||
});
|
||||
}
|
||||
|
||||
var payloadSeasons = new List<TraktSeasonResource>();
|
||||
payloadSeasons.Add(new TraktSeasonResource
|
||||
{
|
||||
Number = episodeFile.SeasonNumber,
|
||||
Episodes = payloadEpisodes
|
||||
});
|
||||
|
||||
payload.Shows.Add(new TraktCollectShow
|
||||
{
|
||||
Title = series.Title,
|
||||
Year = series.Year,
|
||||
Ids = new TraktShowIdsResource
|
||||
{
|
||||
Tvdb = series.TvdbId,
|
||||
Imdb = series.ImdbId ?? "",
|
||||
},
|
||||
Seasons = payloadSeasons,
|
||||
});
|
||||
|
||||
_proxy.RemoveFromCollection(payload, settings.AccessToken);
|
||||
}
|
||||
|
||||
public void RemoveSeriesFromCollection(TraktSettings settings, Series series)
|
||||
{
|
||||
var payload = new TraktCollectShowsResource
|
||||
{
|
||||
Shows = new List<TraktCollectShow>()
|
||||
};
|
||||
|
||||
payload.Shows.Add(new TraktCollectShow
|
||||
{
|
||||
Title = series.Title,
|
||||
Year = series.Year,
|
||||
Ids = new TraktShowIdsResource
|
||||
{
|
||||
Tvdb = series.TvdbId,
|
||||
Imdb = series.ImdbId ?? "",
|
||||
},
|
||||
});
|
||||
|
||||
_proxy.RemoveFromCollection(payload, settings.AccessToken);
|
||||
}
|
||||
|
||||
private string MapMediaType(QualitySource source)
|
||||
{
|
||||
var traktSource = string.Empty;
|
||||
|
||||
switch (source)
|
||||
{
|
||||
case QualitySource.Web:
|
||||
case QualitySource.WebRip:
|
||||
traktSource = "digital";
|
||||
break;
|
||||
case QualitySource.BlurayRaw:
|
||||
case QualitySource.Bluray:
|
||||
traktSource = "bluray";
|
||||
break;
|
||||
case QualitySource.Television:
|
||||
case QualitySource.TelevisionRaw:
|
||||
traktSource = "vhs";
|
||||
break;
|
||||
case QualitySource.DVD:
|
||||
traktSource = "dvd";
|
||||
break;
|
||||
}
|
||||
|
||||
return traktSource;
|
||||
}
|
||||
|
||||
private string MapResolution(int resolution, string scanType)
|
||||
{
|
||||
var traktResolution = string.Empty;
|
||||
|
||||
// var interlacedTypes = new string[] { "Interlaced", "MBAFF", "PAFF" };
|
||||
var scanIdentifier = scanType.IsNotNullOrWhiteSpace() && TraktInterlacedTypes.interlacedTypes.Contains(scanType) ? "i" : "p";
|
||||
|
||||
switch (resolution)
|
||||
{
|
||||
case 2160:
|
||||
traktResolution = "uhd_4k";
|
||||
break;
|
||||
case 1080:
|
||||
traktResolution = $"hd_1080{scanIdentifier}";
|
||||
break;
|
||||
case 720:
|
||||
traktResolution = "hd_720p";
|
||||
break;
|
||||
case 576:
|
||||
traktResolution = $"sd_576{scanIdentifier}";
|
||||
break;
|
||||
case 480:
|
||||
traktResolution = $"sd_480{scanIdentifier}";
|
||||
break;
|
||||
}
|
||||
|
||||
return traktResolution;
|
||||
}
|
||||
|
||||
private string MapAudio(EpisodeFile episodeFile)
|
||||
{
|
||||
var traktAudioFormat = string.Empty;
|
||||
|
||||
var audioCodec = episodeFile.MediaInfo != null ? MediaInfoFormatter.FormatAudioCodec(episodeFile.MediaInfo, episodeFile.SceneName) : string.Empty;
|
||||
|
||||
switch (audioCodec)
|
||||
{
|
||||
case "AC3":
|
||||
traktAudioFormat = "dolby_digital";
|
||||
break;
|
||||
case "EAC3":
|
||||
traktAudioFormat = "dolby_digital_plus";
|
||||
break;
|
||||
case "TrueHD":
|
||||
traktAudioFormat = "dolby_truehd";
|
||||
break;
|
||||
case "EAC3 Atmos":
|
||||
traktAudioFormat = "dolby_digital_plus_atmos";
|
||||
break;
|
||||
case "TrueHD Atmos":
|
||||
traktAudioFormat = "dolby_atmos";
|
||||
break;
|
||||
case "DTS":
|
||||
case "DTS-ES":
|
||||
traktAudioFormat = "dts";
|
||||
break;
|
||||
case "DTS-HD MA":
|
||||
traktAudioFormat = "dts_ma";
|
||||
break;
|
||||
case "DTS-HD HRA":
|
||||
traktAudioFormat = "dts_hr";
|
||||
break;
|
||||
case "DTS-X":
|
||||
traktAudioFormat = "dts_x";
|
||||
break;
|
||||
case "MP3":
|
||||
traktAudioFormat = "mp3";
|
||||
break;
|
||||
case "MP2":
|
||||
traktAudioFormat = "mp2";
|
||||
break;
|
||||
case "Vorbis":
|
||||
traktAudioFormat = "ogg";
|
||||
break;
|
||||
case "WMA":
|
||||
traktAudioFormat = "wma";
|
||||
break;
|
||||
case "AAC":
|
||||
traktAudioFormat = "aac";
|
||||
break;
|
||||
case "PCM":
|
||||
traktAudioFormat = "lpcm";
|
||||
break;
|
||||
case "FLAC":
|
||||
traktAudioFormat = "flac";
|
||||
break;
|
||||
case "Opus":
|
||||
traktAudioFormat = "ogg_opus";
|
||||
break;
|
||||
}
|
||||
|
||||
return traktAudioFormat;
|
||||
}
|
||||
|
||||
private string MapAudioChannels(EpisodeFile episodeFile, string audioFormat)
|
||||
{
|
||||
var audioChannels = episodeFile.MediaInfo != null ? MediaInfoFormatter.FormatAudioChannels(episodeFile.MediaInfo).ToString("0.0") : string.Empty;
|
||||
|
||||
return audioChannels;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue