Added rewatching support
This commit is contained in:
@@ -24,13 +24,14 @@ namespace Jellyfin.Plugin.AnilistSync.API
|
||||
private readonly IHttpClientFactory _httpClientFactory;
|
||||
private readonly JsonSerializerOptions _jsonSerializerOptions;
|
||||
|
||||
private const string listIdQuery = @"mutation ($mediaId: Int) {SaveMediaListEntry(mediaId: $mediaId) {id, status}}&variables={""mediaId"": ""{0}""}";
|
||||
private const string listUpdateQuery = @"mutation ($id: Int, $progress: Int, $status: MediaListStatus) {SaveMediaListEntry(id: $id, progress: $progress, status: $status) {id, progress, status}}";
|
||||
private const string listIdQuery = @"mutation ($mediaId: Int) {SaveMediaListEntry(mediaId: $mediaId) {id, status, repeat}}&variables={""mediaId"": ""{0}""}";
|
||||
private const string listUpdateQuery = @"mutation ($id: Int, $progress: Int, $status: MediaListStatus, $repeat: Int) {SaveMediaListEntry(id: $id, progress: $progress, status: $status, repeat: $repeat) {id, progress, status, repeat}}";
|
||||
private const string episodeQuery = @"query ($id: Int) {Media (id: $id) {episodes}}";
|
||||
private const string currentUserQuery = @"query {Viewer {id, name}}";
|
||||
|
||||
private const string listUpdateVars1 = @"&variables={""id"":""{0}"", ""progress"":""{1}""}";
|
||||
private const string listUpdateVars2 = @"&variables={""id"":""{0}"", ""progress"":""{1}"", ""status"":""{2}""}";
|
||||
private const string listUpdateVars3 = @"&variables={""id"":""{0}"", ""progress"":""{1}"", ""status"":""{2}"", ""repeat"":""{3}""}";
|
||||
|
||||
public const string BaseOauthUrl = @"https://anilist.co/api/v2";
|
||||
public const string BaseGraphQLUrl = @"https://graphql.anilist.co/api/v2?query=";
|
||||
@@ -60,7 +61,9 @@ namespace Jellyfin.Plugin.AnilistSync.API
|
||||
public async Task<RootObject?> GetUser(string? userToken)
|
||||
{
|
||||
var requestMessage = new HttpRequestMessage();
|
||||
requestMessage.RequestUri = new Uri(BaseGraphQLUrl + currentUserQuery);
|
||||
requestMessage.RequestUri = new Uri(
|
||||
BaseGraphQLUrl +
|
||||
currentUserQuery);
|
||||
requestMessage.Method = HttpMethod.Post;
|
||||
requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", userToken);
|
||||
requestMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
|
||||
@@ -76,10 +79,12 @@ namespace Jellyfin.Plugin.AnilistSync.API
|
||||
return data;
|
||||
}
|
||||
|
||||
public async Task<RootObject?> GetListId(string anilistId, string? userToken)
|
||||
public async Task<RootObject?> GetListEntry(string anilistId, string? userToken)
|
||||
{
|
||||
var requestMessage = new HttpRequestMessage();
|
||||
requestMessage.RequestUri = new Uri(BaseGraphQLUrl + listIdQuery.Replace("{0}", anilistId));
|
||||
requestMessage.RequestUri = new Uri(
|
||||
BaseGraphQLUrl +
|
||||
listIdQuery.Replace("{0}", anilistId));
|
||||
requestMessage.Method = HttpMethod.Post;
|
||||
requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", userToken);
|
||||
requestMessage.Content = new StringContent("", Encoding.UTF8, "application/json");
|
||||
@@ -95,7 +100,10 @@ namespace Jellyfin.Plugin.AnilistSync.API
|
||||
public async Task<RootObject?> GetEpisodes(string anilistId)
|
||||
{
|
||||
var requestMessage = new HttpRequestMessage();
|
||||
requestMessage.RequestUri = new Uri(BaseGraphQLUrl + episodeQuery + $"&variables={{\"id\":{anilistId}}}");
|
||||
requestMessage.RequestUri = new Uri(
|
||||
BaseGraphQLUrl +
|
||||
episodeQuery +
|
||||
$"&variables={{\"id\":{anilistId}}}");
|
||||
requestMessage.Method = HttpMethod.Post;
|
||||
requestMessage.Content = new StringContent("", Encoding.UTF8, "application/json");
|
||||
var responseMessage = await _httpClientFactory.CreateClient(NamedClient.Default).SendAsync(requestMessage);
|
||||
@@ -107,12 +115,17 @@ namespace Jellyfin.Plugin.AnilistSync.API
|
||||
return data;
|
||||
}
|
||||
|
||||
public async Task<RootObject?> PostListUpdate(string anilistId, string? userToken, int? progress, MediaListStatus status)
|
||||
public async Task<RootObject?> PostListUpdate(string? anilistMediaId, string? userToken, int? progress, MediaListStatus? status, int? timesRewatched)
|
||||
{
|
||||
var listEntry = GetListId(anilistId, userToken).Result?.Data?.ListEntry;
|
||||
|
||||
var requestMessage = new HttpRequestMessage();
|
||||
requestMessage.RequestUri = new Uri(BaseGraphQLUrl + listUpdateQuery + listUpdateVars2.Replace("{0}", listEntry?.Id.ToString()).Replace("{1}", progress.ToString()).Replace("{2}", status.ToString()));
|
||||
requestMessage.RequestUri = new Uri(
|
||||
BaseGraphQLUrl +
|
||||
listUpdateQuery +
|
||||
listUpdateVars3
|
||||
.Replace("{0}", anilistMediaId)
|
||||
.Replace("{1}", progress.ToString())
|
||||
.Replace("{2}", status.ToString())
|
||||
.Replace("{3}", timesRewatched.ToString()));
|
||||
requestMessage.Method = HttpMethod.Post;
|
||||
requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", userToken);
|
||||
requestMessage.Content = new StringContent("", Encoding.UTF8, "application/json");
|
||||
|
||||
@@ -71,6 +71,9 @@ namespace Jellyfin.Plugin.AnilistSync.API
|
||||
|
||||
[JsonPropertyName("status")]
|
||||
public MediaListStatus? Status { get; set; }
|
||||
|
||||
[JsonPropertyName("repeat")]
|
||||
public int? TimesRewatched { get; set; }
|
||||
}
|
||||
|
||||
public enum MediaListStatus
|
||||
|
||||
@@ -73,7 +73,6 @@ namespace Jellyfin.Plugin.AnilistSync.Services
|
||||
}
|
||||
|
||||
// Checks if runtime is greater than min length to be scrobbled
|
||||
// TODO: chan 5 to configurable value
|
||||
if (runtime < 60 * 10000 * userConfig.MinLength)
|
||||
{
|
||||
return false;
|
||||
@@ -163,21 +162,46 @@ namespace Jellyfin.Plugin.AnilistSync.Services
|
||||
anilistId);
|
||||
|
||||
|
||||
// Send post request to API to update list
|
||||
int? episodes = (await _anilistApi.GetEpisodes(anilistId))?.Data?.Media?.Episodes;
|
||||
// Get the list entry for current watching show from Anilist
|
||||
var listEntry = _anilistApi.GetListEntry(anilistId, userConfig.UserToken).Result?.Data?.ListEntry;
|
||||
|
||||
int? currentIndex = eventArgs.Item.IndexNumber;
|
||||
|
||||
_logger.LogInformation("Total Episodes: " + episodes.ToString());
|
||||
_logger.LogInformation("Current Episode: " + currentIndex.ToString());
|
||||
int? timesRewatched = listEntry?.TimesRewatched;
|
||||
MediaListStatus? status = listEntry?.Status;
|
||||
|
||||
MediaListStatus status = MediaListStatus.CURRENT;
|
||||
// Check if STARTING a rewatch
|
||||
if (status == MediaListStatus.COMPLETED)
|
||||
{
|
||||
if (currentIndex == 1) // Check rewatching first episode
|
||||
{
|
||||
status = MediaListStatus.REPEATING;
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogDebug("Attempting to start rewatch from middle episode, discarding scrobble");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Get total number of episodes of current item from Anilist
|
||||
int? episodes = (await _anilistApi.GetEpisodes(anilistId))?.Data?.Media?.Episodes;
|
||||
_logger.LogInformation("Total Episodes: {totalEpisodes}", episodes);
|
||||
_logger.LogInformation("Current Episode: {currentEpisode}", currentIndex);
|
||||
|
||||
// If watching LAST episode change status to completed
|
||||
if (currentIndex == episodes)
|
||||
{
|
||||
if (status == MediaListStatus.REPEATING)
|
||||
{
|
||||
timesRewatched += 1;
|
||||
}
|
||||
status = MediaListStatus.COMPLETED;
|
||||
}
|
||||
_logger.LogInformation(status.ToString());
|
||||
_logger.LogInformation("Current watch status: {status}", status);
|
||||
|
||||
var response = await _anilistApi.PostListUpdate(anilistId, userConfig.UserToken, currentIndex, status);
|
||||
// Send post request to API to update list
|
||||
var response = await _anilistApi.PostListUpdate(listEntry?.Id.ToString(), userConfig.UserToken, currentIndex, status, timesRewatched);
|
||||
_logger.LogDebug("Scrobbled without errors");
|
||||
_lastScrobbled[eventArgs.Session.Id] = eventArgs.MediaInfo.Id;
|
||||
|
||||
@@ -186,11 +210,11 @@ namespace Jellyfin.Plugin.AnilistSync.Services
|
||||
//{
|
||||
// _logger.LogDebug("Deleted user token");
|
||||
//}
|
||||
catch (AnilistAPIException alEx)
|
||||
catch (AnilistAPIException aniAPIEx)
|
||||
{
|
||||
for (int i = 0; i < alEx.errors?.Length; i++)
|
||||
for (int i = 0; i < aniAPIEx.errors?.Length; i++)
|
||||
{
|
||||
Error? error = alEx.errors[i];
|
||||
Error? error = aniAPIEx.errors[i];
|
||||
_logger.LogError(error.ErrorMessage, "API response code " + error.ErrorStatus);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user