From a6a5c541e303f1cbd20a86e91f24f153f610328e Mon Sep 17 00:00:00 2001 From: Harshith Mohan <26010946+harshithmohan@users.noreply.github.com> Date: Sat, 21 Dec 2024 01:53:42 +0530 Subject: [PATCH] Add UpdateTraktShowJob, trakt series sync/refresh endpoints (#1211) - Add endpoint to sync Trakt series - Add endpoint to update series Trakt data --- .../API/v3/Controllers/SeriesController.cs | 84 +++++++++++++++++++ .../Jobs/Trakt/UpdateTraktShowJob.cs | 59 +++++++++++++ 2 files changed, 143 insertions(+) create mode 100644 Shoko.Server/Scheduling/Jobs/Trakt/UpdateTraktShowJob.cs diff --git a/Shoko.Server/API/v3/Controllers/SeriesController.cs b/Shoko.Server/API/v3/Controllers/SeriesController.cs index fe35c49d1..d1701bbb3 100644 --- a/Shoko.Server/API/v3/Controllers/SeriesController.cs +++ b/Shoko.Server/API/v3/Controllers/SeriesController.cs @@ -31,6 +31,7 @@ using Shoko.Server.Repositories.Cached; using Shoko.Server.Scheduling; using Shoko.Server.Scheduling.Jobs.Shoko; +using Shoko.Server.Scheduling.Jobs.Trakt; using Shoko.Server.Services; using Shoko.Server.Settings; using Shoko.Server.Utilities; @@ -114,6 +115,8 @@ WatchedStatusService watchedService internal const string TmdbNotFoundForSeriesID = "No TMDB.Show entry for the given seriesID"; internal const string TmdbForbiddenForUser = "Accessing TMDB.Show is not allowed for the current user"; + + internal const string TraktShowNotFound = "No Trakt_Show entry for the given showID"; #endregion @@ -1779,6 +1782,87 @@ public ActionResult> GetTMDBSeasonsBySeriesID( #endregion + #endregion + + #region Trakt + + /// + /// Queue a job for refreshing series data from Trakt + /// + /// Shoko ID + /// + [HttpPost("{seriesID}/Trakt/Refresh")] + public async Task RefreshTraktBySeriesID([FromRoute, Range(1, int.MaxValue)] int seriesID) + { + var series = RepoFactory.AnimeSeries.GetByID(seriesID); + if (series == null) + { + return NotFound(SeriesNotFoundWithSeriesID); + } + + if (!User.AllowedSeries(series)) + { + return Forbid(SeriesForbiddenForUser); + } + + var anidb = series.AniDB_Anime; + if (anidb == null) + { + return InternalError(AnidbNotFoundForSeriesID); + } + + var traktShows = series.TraktShow; + if (traktShows.Count == 0) + { + return ValidationProblem(TraktShowNotFound); + } + + var scheduler = await _schedulerFactory.GetScheduler(); + + foreach(var show in traktShows) + { + await scheduler.StartJob(c => c.TraktShowID = show.TraktID); + } + + return Ok(); + } + + /// + /// Queue a job for syncing series status to Trakt + /// + /// Shoko ID + /// + [HttpPost("{seriesID}/Trakt/Sync")] + public async Task SyncTraktBySeriesID([FromRoute, Range(1, int.MaxValue)] int seriesID) + { + var series = RepoFactory.AnimeSeries.GetByID(seriesID); + if (series == null) + { + return NotFound(SeriesNotFoundWithSeriesID); + } + + if (!User.AllowedSeries(series)) + { + return Forbid(SeriesForbiddenForUser); + } + + var anidb = series.AniDB_Anime; + if (anidb == null) + { + return InternalError(AnidbNotFoundForSeriesID); + } + + var traktShows = series.TraktShow; + if (traktShows.Count == 0) + { + return ValidationProblem(TraktShowNotFound); + } + + var scheduler = await _schedulerFactory.GetScheduler(); + await scheduler.StartJob(c => c.AnimeSeriesID = seriesID); + return Ok(); + } + #endregion #endregion diff --git a/Shoko.Server/Scheduling/Jobs/Trakt/UpdateTraktShowJob.cs b/Shoko.Server/Scheduling/Jobs/Trakt/UpdateTraktShowJob.cs new file mode 100644 index 000000000..863c85519 --- /dev/null +++ b/Shoko.Server/Scheduling/Jobs/Trakt/UpdateTraktShowJob.cs @@ -0,0 +1,59 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Shoko.Server.Providers.TraktTV; +using Shoko.Server.Repositories; +using Shoko.Server.Scheduling.Acquisition.Attributes; +using Shoko.Server.Scheduling.Attributes; +using Shoko.Server.Scheduling.Concurrency; +using Shoko.Server.Settings; + +namespace Shoko.Server.Scheduling.Jobs.Trakt; + +[DatabaseRequired] +[NetworkRequired] +[DisallowConcurrencyGroup(ConcurrencyGroups.Trakt)] +[JobKeyGroup(JobKeyGroup.Trakt)] +public class UpdateTraktShowJob : BaseJob +{ + private readonly ISettingsProvider _settingsProvider; + private readonly TraktTVHelper _helper; + private string _showName; + public string TraktShowID { get; set; } + + public override string TypeName => "Update Trakt Show data"; + public override string Title => "Updating Trakt Show data"; + + public override void PostInit() + { + _showName = RepoFactory.Trakt_Show?.GetByTraktSlug(TraktShowID)?.Title ?? TraktShowID; + } + + public override Dictionary Details => new() { { "Show", _showName } }; + + public override Task Process() + { + _logger.LogInformation("Processing {Job} -> Show: {Name}", nameof(UpdateTraktShowJob), _showName); + var settings = _settingsProvider.GetSettings(); + if (!settings.TraktTv.Enabled || string.IsNullOrEmpty(settings.TraktTv.AuthToken)) return Task.CompletedTask; + + var show = RepoFactory.Trakt_Show.GetByTraktSlug(TraktShowID); + if (show == null) + { + _logger.LogError("Could not find trakt show: {TraktShowID}", TraktShowID); + return Task.CompletedTask; + } + + _helper.UpdateAllInfo(TraktShowID); + + return Task.CompletedTask; + } + + public UpdateTraktShowJob(TraktTVHelper helper, ISettingsProvider settingsProvider) + { + _helper = helper; + _settingsProvider = settingsProvider; + } + + protected UpdateTraktShowJob() { } +}