Giter Club home page Giter Club logo

simple-justwatch-python-api's Introduction

Simple JustWatch Python API

CodeQL Black Flake8 isort Pytest Coverage Status PyPI - Version

A simple unofficial JustWatch Python API which uses GraphQL to access JustWatch data, built with httpx and Python3.11.

Table of contents

Installation

Project is available in PyPi:

pip install simple-justwatch-python-api

Usage

This Python API has 3 functions:

  • search - search for entries based on title
  • details - get details for entry based on its node ID
  • offers_for_countries - get offers for entry based on its node ID, can look for offers in multiple countries

Detailed documentation is available in https://electronic-mango.github.io/simple-justwatch-python-api/.

Example outputs from all commands are in examples/ directory.

Search

Search functions allows for searching entries based on a given title.

from simplejustwatchapi.justwatch import search

results = search("title", "US", "en", 5, True)

Only the first argument is required, it specifies a title to search.

Argument Type Required Default value Description
1 title str YES - Title to look up
2 country str NO "US" Country to search for offers
3 language str NO "en" Language of responses
4 count int NO 4 Up to how many entries should be returned
5 best_only bool NO True Determines whether only best offers should be returned

country must be ISO 3166-1 alpha-2 2-letter code , e.g. US, GB, FR. It should be uppercase, however lowercase codes are automatically converted to uppercase.

language is a ISO 639-1 (usually) 2-letter code, lowercase, e.g. en, fr.

count determines up to how many entries should be returned. If JustWatch GraphQL API returns fewer entries, then this function will also return fewer values.

best_only determines whether similar offers, but lower quality should be included in response. If a platform offers streaming for a given entry in 4K, HD and SD, then best_only = True will return only the 4K offer, best_only = False will return all three.

Returned value is a list of MediaEntry objects.

Example command and its output is in examples/search_output.py.

Details

Details function allows for looking up details for a single entry via its node ID. Node ID can be taken from output of the search command.

Output from this function contains the same data as a single entry from the search command. There's no reason to first use the search command, then use node ID from one of entries for this command.

from simplejustwatchapi.justwatch import details

results = details("nodeID", "US", "en", False)

Only the first argument is required - the node ID of element to look up details for.

Argument Type Required Default value Description
1 node_id str YES - Node ID to look up
2 country str NO "US" Country to search for offers
3 language str NO "en" Language of responses
5 best_only bool NO True Determines whether only best offers should be returned

General usage of these arguments matches the search command.

Returned value is a single MediaEntry object.

Example command and its output is in examples/details_output.py.

Offers for countries

This function allows looking up offers for entry by given node ID. It allows specifying a set of countries, instead of a single one. This way you can simultaneously look up offers for multiple countries.

from simplejustwatchapi.justwatch import offers_for_countries

results = offers_for_countries("nodeID", {"US", "UK", "CA"}, "en", True)

First two arguments are required - node ID, and set of countries.

Argument Type Required Default value Description
1 node_id str YES - Node ID to look up
2 countries set[str] YES - Set of countries to look up offers for
3 language str NO "en" Language of responses
5 best_only bool NO True Determines whether only best offers should be returned

Usage of language and best_only arguments matches the search command.

Returned value dict[str, list[Offer]], where key is country given as argument and value is a list of Offer tuples.

Example command and its output is in examples/offers_for_countries_output.py.

Return data structures

Detailed descriptions of all used data structures are available in the documentation.

Locale, language, country

Languages and countries are configured via ISO standard. Countries are following ISO 3166-1 alpha-2 standard (2-letter codes, uppercase). Languages are following ISO 639-1 standard (usually 2-letter codes, lowercase).

Language codes can also be country-specific, e.g. es-MX for Mexican Spanish, etc. The country part must be uppercase.

There is a list of supported locales in JustWatch REST API documentation. Any combination of those languages and countries should work with this API as well.

If you provide unsupported language JustWatch API should default to english.

Disclaimer

This API is in no way affiliated, associated, authorized, endorsed by, or in any way officially connected with JustWatch. This is an independent and unofficial project. Use at your own risk.

simple-justwatch-python-api's People

Contributors

electronic-mango avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

simple-justwatch-python-api's Issues

Add support for getting the length of a film

I think this is as simple as the following (which seems to work), but I expect there are other things to update like tests / readmes etc.

There might be other things needed I guess to cope with TV Series or whatever (I don't know how consistent the runtime thing is - I only tested it on a couple of films).

diff --git a/src/simplejustwatchapi/query.py b/src/simplejustwatchapi/query.py
index b506a89..e71fbbe 100644
--- a/src/simplejustwatchapi/query.py
+++ b/src/simplejustwatchapi/query.py
@@ -55,6 +55,7 @@ fragment SearchTitleGraphql on PopularTitlesEdge {
         __typename
       }
       posterUrl(profile: $profile, format: $formatPoster)
+      runtime
       backdrops(profile: $backdropProfile, format: $formatPoster) {
         backdropUrl
         __typename
@@ -117,6 +118,7 @@ class MediaEntry(NamedTuple):
     genres: list[str]
     imdb_id: str | None
     poster: str | None
+    runtime_mins: int
     backdrops: list[str]
     offers: list[Offer]

@@ -185,6 +187,7 @@ def _parse_entry(json: any) -> MediaEntry:
     imdb_id = external_ids.get("imdbId") if external_ids else None
     poster_url_field = content.get("posterUrl")
     poster = _IMAGES_URL + poster_url_field if poster_url_field else None
+    runtime_mins = content.get("runtime")
     backdrops = [_IMAGES_URL + bd.get("backdropUrl") for bd in content.get("backdrops", []) if bd]
     offers = [_parse_offer(offer) for offer in json.get("offers", []) if offer]
     return MediaEntry(
@@ -198,6 +201,7 @@ def _parse_entry(json: any) -> MediaEntry:
         genres,
         imdb_id,
         poster,
+        runtime_mins,
         backdrops,
         offers,
     )

NEW FUNCTIONALITY REQUEST: Down to Season/Episode Offers

Thanks for putting this together! I'm working on a project for a user to search for a program and then select from the resulting list of Offers for which one they would want. This, in turn, creates a file for the purposes of Deep Linking. Overall, I've got it working as a proof of concept thanks to your API.

Now, I'm wondering if you can take it to the next level down? The Offer URL work great for movies. However, for shows, the ones that come back are either to the series' page or the first episode. I'd like to be able to query against a selected program, then against a selected season, and then finally get the offers per episode. The data is available on JustWatch, and is pretty decent, but is buried pretty far down.

Invalid handling of NoneType

I installed this module today and tried it (with python 3.10.12 as that's the system python - I know the README says python 3.11 but I don't want to update at the moment.

I found what I hope is a minor bug:

Python 3.10.12 (main, Nov 20 2023, 15:14:05) [GCC 11.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from simplejustwatchapi import search
>>> result = search('Die Hard', 'GB', 'en', 10)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File ".../simplejustwatchapi/justwatch.py", line 31, in search
    return parse_search_response(response.json())
  File ".../simplejustwatchapi/query.py", line 168, in parse_search_response
    entries = [_parse_entry(node["node"]) for node in nodes]
  File ".../simplejustwatchapi/query.py", line 168, in <listcomp>
    entries = [_parse_entry(node["node"]) for node in nodes]
  File ".../simplejustwatchapi/query.py", line 184, in _parse_entry
    poster = _IMAGES_URL + content.get("posterUrl")
TypeError: can only concatenate str (not "NoneType") to str

Presumably the API has returned something invalid (or nothing at all) for the posterUrl.

providers

is it possible to list providers home page and justwatch page?

[feature] Implement other graphql request

2 queries I would love to see in this library

GetTitleOffers (with a list of countries as input):

private static string _GetTitleOffersQuery(IEnumerable<string> countries)
	{
		string query = @"
query GetTitleOffers($nodeId: ID!, $language: Language!, $filterBuy: OfferFilter!, $platform: Platform! = WEB) {
  node(id: $nodeId) {

    ... on MovieOrShowOrSeasonOrEpisode {
      
      ";

		foreach (var country in countries)
		{
			query += $@"
      {country.ToLower()}: offers(country: {country}, platform: $platform, filter: $filterBuy) {{
        ...TitleOffer
        __typename
      }}";
		}
		query += @"
    }
  }
}

fragment TitleOffer on Offer {
  id
  presentationType
  monetizationType
  retailPrice(language: $language)
  retailPriceValue
  currency
  lastChangeRetailPriceValue
  type
  package {
    id
    packageId
    clearName
    technicalName
    icon(profile: S100)
    __typename
  }
  standardWebURL
  elementCount
  availableTo
  deeplinkRoku: deeplinkURL(platform: ROKU_OS)
  subtitleLanguages
  videoTechnology
  audioTechnology
  audioLanguages
  __typename
}";

		return query;
	}

This one is maybe also handy to get details by the NodeID

query GetTitleNode(
  $nodeId: ID!, 
  $language: Language!, 
  $country: Country!,
  $formatPoster: ImageFormat,
  $profile: PosterProfile,
  $backdropProfile: BackdropProfile) {
  node(id: $nodeId) {
 
   ... on MovieOrShow {
    id
    objectId
    objectType
    content(country: $country, language: $language) {
      title
      fullPath
      originalReleaseYear
      originalReleaseDate
      runtime
      shortDescription
      genres {
        shortName
        __typename
      }
      externalIds {
        imdbId
        tmdbId
        __typename
      }
      posterUrl(profile: $profile, format: $formatPoster)
      backdrops(profile: $backdropProfile, format: $formatPoster) {
        backdropUrl
        __typename
      }
      __typename
    }

    __typename
  }
}
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.