Skip to content

Commit

Permalink
Use Plex API to get file path for webhooks
Browse files Browse the repository at this point in the history
  • Loading branch information
LordFlashmeow committed Jun 12, 2024
1 parent a0789b3 commit 56ffc8b
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 27 deletions.
73 changes: 47 additions & 26 deletions Shoko.Server/API/v2/Modules/PlexWebhook.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,15 @@
using Shoko.Models.Enums;
using Shoko.Models.Plex.Collection;
using Shoko.Models.Plex.Connections;
using Shoko.Models.Plex.Libraries;
using Shoko.Models.Plex.TVShow;
using Shoko.Models.Server;
using Shoko.Server.API.v2.Models.core;
using Shoko.Server.Extensions;
using Shoko.Server.Models;
using Shoko.Server.Plex;
using Shoko.Server.Plex.Collection;
using Shoko.Server.Plex.Libraries;
using Shoko.Server.Plex.TVShow;
using Shoko.Server.Providers.TraktTV;
using Shoko.Server.Repositories;
using Shoko.Server.Scheduling;
Expand Down Expand Up @@ -60,20 +62,29 @@ public ActionResult WebhookPost([FromForm] [ModelBinder(BinderType = typeof(Plex
}

_logger.LogTrace($"{payload.Event}: {payload.Metadata?.Guid}");

var user = User;
user ??= RepoFactory.JMMUser.GetAll().FirstOrDefault(u => payload.Account.Title.FindIn(u.GetPlexUsers()));
if (user == null)
{
_logger.LogInformation("Unable to determine who \"{AccountTitle}\" is in Shoko, make sure this is set under user settings in Desktop", payload.Account.Title);
return Ok(); //At this point in time, we don't want to scrobble for unknown users
}

switch (payload.Event)
{
case "media.scrobble":
Scrobble(payload, User);
Scrobble(payload, user);
break;
case "media.resume":
case "media.play":
TraktScrobble(payload, ScrobblePlayingStatus.Start);
TraktScrobble(payload, ScrobblePlayingStatus.Start, user);
break;
case "media.pause":
TraktScrobble(payload, ScrobblePlayingStatus.Pause);
TraktScrobble(payload, ScrobblePlayingStatus.Pause, user);
break;
case "media.stop":
TraktScrobble(payload, ScrobblePlayingStatus.Stop);
TraktScrobble(payload, ScrobblePlayingStatus.Stop, user);
break;
}

Expand All @@ -84,15 +95,15 @@ public ActionResult WebhookPost([FromForm] [ModelBinder(BinderType = typeof(Plex
#region Plex events

[NonAction]
private void TraktScrobble(PlexEvent evt, ScrobblePlayingStatus type)
private void TraktScrobble(PlexEvent evt, ScrobblePlayingStatus type, JMMUser user)
{
var metadata = evt.Metadata;
var (episode, _) = GetEpisode(metadata);
var (episode, _) = GetEpisode(metadata, user);

if (episode == null) return;

var vl = RepoFactory.VideoLocal.GetByAniDBEpisodeID(episode.AniDB_EpisodeID).FirstOrDefault();
if (vl == null || vl.Duration == 0) return;
if (vl == null || vl.Duration == 0) return;

var per = 100 *
(metadata.ViewOffset /
Expand All @@ -109,7 +120,7 @@ private void TraktScrobble(PlexEvent evt, ScrobblePlayingStatus type)
private void Scrobble(PlexEvent data, SVR_JMMUser user)
{
var metadata = data.Metadata;
var (episode, anime) = GetEpisode(metadata);
var (episode, anime) = GetEpisode(metadata, user);
if (episode == null)
{
_logger.LogInformation(
Expand All @@ -119,12 +130,6 @@ private void Scrobble(PlexEvent data, SVR_JMMUser user)

_logger.LogTrace("Got anime: {Anime}, ep: {EpisodeNumber}", anime, episode.AniDB_Episode.EpisodeNumber);

user ??= RepoFactory.JMMUser.GetAll().FirstOrDefault(u => data.Account.Title.FindIn(u.GetPlexUsers()));
if (user == null)
{
_logger.LogInformation("Unable to determine who \"{AccountTitle}\" is in Shoko, make sure this is set under user settings in Desktop", data.Account.Title);
return; //At this point in time, we don't want to scrobble for unknown users
}

episode.ToggleWatchedStatus(true, true, FromUnixTime(metadata.LastViewedAt), false, user.JMMUserID,
true);
Expand All @@ -135,7 +140,7 @@ private void Scrobble(PlexEvent data, SVR_JMMUser user)
#endregion

[NonAction]
private (SVR_AnimeEpisode, SVR_AnimeSeries) GetEpisode(PlexEvent.PlexMetadata metadata)
private (SVR_AnimeEpisode, SVR_AnimeSeries) GetEpisode(PlexEvent.PlexMetadata metadata, JMMUser user)
{
var guid = new Uri(metadata.Guid);
if (guid.Scheme != "com.plexapp.agents.shoko" && guid.Scheme != "com.plexapp.agents.shokorelay")
Expand Down Expand Up @@ -179,20 +184,29 @@ private void Scrobble(PlexEvent data, SVR_JMMUser user)
break;
}

var key = metadata.Key.Split("/").LastOrDefault(); // '/library/metadata/{key}'

var plexEpisode = (SVR_Episode)GetPlexEpisodeData(key, user);
var episode = plexEpisode?.AnimeEpisode;

if (episodeType != EpisodeType.Episode ||
metadata.Index == 0) //metadata.index = 0 when it's something else.
{
var nameMatches = anime
.GetAnimeEpisodes().Where(a => a.AniDB_Episode != null)
.Where(a => a.EpisodeTypeEnum == episodeType)
.Where(a => a.Title.Equals(metadata.Title))
.Where(a => a.AniDB_Episode.EpisodeNumber == episodeNumber
|| (a.TvDBEpisode?.SeasonNumber == series && a.TvDBEpisode?.EpisodeNumber == episodeNumber)).ToList();

if (nameMatches.Count == 1) return (nameMatches.First(), anime);
if (episode == null)
{
_logger.LogInformation(
$"Failed to get anime episode from plex using key {metadata.Key}.");
return (null, anime);
}

if (episode.EpisodeTypeEnum == episodeType
&& anime.GetAnimeEpisodes().Contains(episode))
{
return (episode, anime);
}

_logger.LogInformation(
$"Unable to work out the metadata for {metadata.Guid} using title {metadata.Title}.");
$"Unable to work out the metadata for {metadata.Guid}.");

return (null, anime);
}
Expand Down Expand Up @@ -285,7 +299,7 @@ public async Task<ActionResult> SyncForUser(int id)

[Authorize]
[HttpGet("libraries")]
public ActionResult<Directory[]> GetLibraries()
public ActionResult<Shoko.Models.Plex.Libraries.Directory[]> GetLibraries()
{
var result = CallPlexHelper(h => h.GetDirectories());

Expand Down Expand Up @@ -347,6 +361,13 @@ private T CallPlexHelper<T>(Func<PlexHelper, T> act)
return act(PlexHelper.GetForUser(user));
}

[NonAction]
private Episode GetPlexEpisodeData(string ratingKey, JMMUser user)
{
var helper = PlexHelper.GetForUser(user);
return new SVR_PlexLibrary(helper).GetEpisode(ratingKey).FirstOrDefault();
}

#region plexapi

#pragma warning disable 0649
Expand Down
11 changes: 10 additions & 1 deletion Shoko.Server/Plex/Collection/SVR_PlexLibrary.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using Newtonsoft.Json;
using Newtonsoft.Json;
using Shoko.Models.Plex;
using Shoko.Models.Plex.Collection;
using Shoko.Models.Plex.TVShow;
Expand All @@ -23,4 +23,13 @@ public Episode[] GetEpisodes()
.DeserializeObject<MediaContainer<MediaContainer>>(data, Helper.SerializerSettings)
.Container.Metadata;
}

public Episode[] GetEpisode(string ratingKey)
{
var (_, data) = Helper.RequestFromPlexAsync($"/library/metadata/{ratingKey}").GetAwaiter()
.GetResult();
return JsonConvert
.DeserializeObject<MediaContainer<MediaContainer>>(data, Helper.SerializerSettings)
.Container.Metadata;
}
}

0 comments on commit 56ffc8b

Please sign in to comment.