Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sync module, limited in updating watchlist / collection #132

Open
p0psicles opened this issue Dec 26, 2020 · 6 comments
Open

sync module, limited in updating watchlist / collection #132

p0psicles opened this issue Dec 26, 2020 · 6 comments

Comments

@p0psicles
Copy link
Contributor

p0psicles commented Dec 26, 2020

hi @moogar0880 I don't know if this project is still alive. But recently I decided to refactor some it's code, as it's kinda limited compared to what the trakt api offers.

One example is the exposure of sync/collection and sync/watchlist.
You'r only allowed to pass one TvShow, TVEpisode or Movie object to it. Where the trakt api offers a number of ways, where you can send multiple episodes, shows or movies to it. This brings some issues as for example. If you want to do batch updates of a number of episodes, you have to call the sync/ route for each episodes. Possibly resulting in rate limiting.

Now i'm able to work around this with the following code:

@post
def add_to_collection(media=None, media_type=None, media_objects=None):
    """Add a :class:`Movie`, :class:`TVShow`, or :class:`TVEpisode` to your
    collection

    The trakt api allows for adding or removing multiple media objects
        through an array. If you want to make us if this.
        Make sure to leave media empty, and pass the media_type
        ('movies', 'shows' or 'episodes')
        and don't pass a value for `media`. Make sure to pass an array of
        media objects to media_objects.

    :param media: The :class:`TVShow` shows, :class:`TVEpisode` episodes,
        or :class:`Movie` movies media object.
    :param media_type: The :string: media type key
    :param media_objects: The :class:`TVShow` shows, :class:`TVEpisode` episodes,
        or :class:`Movie` movies media object.
    """
    valid_type = ('movies', 'shows', 'episodes')

    if media:
        yield 'sync/collection', media.to_json()

    if media_type and media_objects and isinstance(media_objects, list):
        if media_type not in valid_type:
            raise ValueError('media_type must be one of {}'.format(valid_type))

        yield 'sync/collection', {
            media_type: [media_object.to_json_singular()[media_type[:-1]]
                         for media_object in media_objects]
        }

But then the next issue pops up.
For updating episodes, currently it's sending the following object:

{
      "episode": {
          "ids": {
              "trakt": [episode_trakt_id]
          }
      }
}

But we don't have this id available when sending the request.
Now the way it's currently working, is that it will request the trakt id using the show-slug. And there are two issues i have with that.

  1. It's doing an extra request for each episode, while that's not really needed.
  2. It leaves room for error as i'm using slug and not and id (imdb, trakt, tvdb, etc)
    @property
    def ext(self):
        return 'shows/{id}/seasons/{season}/episodes/{episode}'.format(
            id=slugify(self.show), season=self.season, episode=self.number
        )

So i'd prefer to use the forrmat of:

      "title": "Mad Men",
      "year": 2007,
      "ids": {
        "trakt": 4,
        "slug": "mad-men",
        "tvdb": 80337,
        "imdb": "tt0804503",
        "tmdb": 1104
      },
      "seasons": [
        {
          "number": 1,
          "episodes": [
            {
              "number": 1,
              "media_type": "bluray",
              "resolution": "hd_1080p",
              "audio": "dolby_digital_plus",
              "audio_channels": "5.1"
            },
            {
              "number": 2
            }
          ]
        }

But this does not fit into the current architecture of PyTrakt.

An alternative i've considered. Is adding a generec sync route, that just routes and passes along the request to the route that can handle these structures of standard media objects

@p0psicles
Copy link
Contributor Author

i'm going with this for now. As I can't think of a solution where I don't have to rewrite large parts of the code.

@post
def add_to_watchlist(media):
    """Add a :class:`Movie`, :class:`TVShow`, or :class:`TVEpisode`
        to your watchlist
    """
    # Legacy support of using PyTrakt media objects.
    if isinstance(media, (TVEpisode, TVSeason, TVShow, Movie)):
        media_object = media.to_json()
    else:
        media_object = media

    yield 'sync/watchlist', media_object

@moogar0880
Copy link
Owner

hey @p0psicles sorry about the lack of communication. I think I may have gotten overzealous when tuning my github notifications a couple months ago... but, to your questions:

I don't know if this project is still alive... it's kinda limited compared to what the trakt api offers.

It's definitely been a while since I've had the time or need to develop on this library. I'm certainly happy to review/merge PRs or provide feedback/input as needed but I don't think I'll have much in the way of time to start doing heavy development on this library, which it sounds like may be needed.

It's doing an extra request for each episode, while that's not really needed

Is the extra request you're referring to a request to get the trakt_id that PyTrakt is currently trying to send to update a collection? If so it sounds to me like maybe the sync API calls in PyTrakt should be updated to check if there's a way to send a resource being synchronized to trakt without additional API requests?

@p0psicles
Copy link
Contributor Author

p0psicles commented Dec 27, 2020

It comes down to requiring the TVShow().to_json() and TVEpisode().to_json() methods. I understand the initial idea behind it. But in practice it's really limiting the trakt sync api usage.

What would you think of the last code example I posted? In just allowing the user to send it's own dict struct?

@moogar0880
Copy link
Owner

I think allowing users to send their own arbitrary blobs of data should be fine. I'm not entirely sure that the class implementations should be flagged as "legacy", but the approach seems reasonable 👍

@p0psicles
Copy link
Contributor Author

Ooh that's fine. I think I added the legacy comment more to show a user the old and new behavior. But I can remove the comment.

I did some more changes. I'll create one big PR. That you can give your feedback on. Then I can submit one PR per functional change.

Then we can take a look at the documentation. As I noticed it was lagging a bit behind. Is there a place where I can update it?

@moogar0880
Copy link
Owner

I did some more changes. I'll create one big PR. That you can give your feedback on. Then I can submit one PR per functional change.

Sounds good to me 👍

Then we can take a look at the documentation. As I noticed it was lagging a bit behind. Is there a place where I can update it?

All of the docs are automatically generated from the rst files in the docs/ directory, as well as the embedded docstrings on the classes/functions/etc, so you should be able to just update those as you go. Just taking a quick look at the docs directory it seems like nothing in there has changed in several years so I agree that those are very likely overdue for an update.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants