Skip to main content

PlayOn facilities, primarily access to the download API. Includes a nice command line tool.

Project description

PlayOn facilities, primarily access to the download API. Includes a nice command line tool.

Latest release 20260531:

  • DOwnloads: use cs.rfc2616.content_length to get the download content-length, open the download file with 'xb'.
  • PlayOnAPI is now the source of the sqltags, do not expect to access it outside.
  • New _PlayOnEntity(HasSQLTags) base class for Recording and LoginState.
  • PlayOnAPI: new .login_userid property for external use.
  • PlayOnAPI.getitem: an int index is promoted to ('recording,str(index)) for lookup.
  • PlayOnAPI: new .recordings() finding playon.recording.*; use it for iter.
  • PlayOnAPI: new .recording_ids_from_str() method for use by the CLI.
  • PlayOnAPI: use the new UsesTagSets stuff.
  • The PlayOn API has started reciting times with a microsecond field.
  • PlayOnAPI.from_playon_date: accomodate time formats with and without microseconds.
  • Recording.STALE_AGE -> Recording.refresh_lifespan for Refreshable.
  • PlayOnCommand.cmd_dl: use pmap() to run the downloads in parallel.
  • Assorted other internal changes.

Short summary:

  • main: Playon command line mode; see the PlayOnCommand class below.
  • PlayOnAPI: Access to the PlayOn API.
  • PlayOnCommand: Playon command line implementation.
  • PlayonSeriesEpisodeInfo: A SeriesEpisodeInfo with a from_Recording() factory method to build one from a PlayOn Recording instead or other mapping with playon.* keys.
  • PlayOnSQLTags: PlayOn flavoured SQLTags; it just has custom values for the default db location.
  • Recording: A PlayOn recording.

Module contents:

  • main(argv=None): Playon command line mode; see the PlayOnCommand class below.
  • class PlayOnAPI(cs.service_api.HTTPServiceAPI): Access to the PlayOn API.

PlayOnAPI.HasTagsClass

PlayOnAPI.TagSetsClass

PlayOnAPI.__getitem__(self, index: tuple | int) -> cs.tagset.HasTags: If index is an int return the associated Recording. Otherwise index should be a tuple, returns the associated HasTags.

PlayOnAPI.__iter__(self): Iteration iterates over the recordins.

PlayOnAPI.account(self): Return account information.

PlayOnAPI.as_contextmanager(self): Run the generator from the cls class specific __enter_exit__ method via self as a context manager.

Example from RunState which subclasses HasThreadState, both of which are ContextManagerMixin subclasses:

class RunState(HasThreadState):
    .....
    def __enter_exit__(self):
        with HasThreadState.as_contextmanager(self):
            ... RunState context manager stuff ...

This runs the HasThreadState context manager around the main RunState context manager.

PlayOnAPI.auth_token: An auth token obtained from the login state.

PlayOnAPI.available(self): Yield the Recordings.

Note that this includes both recorded and queued items.

PlayOnAPI.by_entity_id(entity_id: str) -> cs.tagset.HasTags: Return the HasTags instance corresponding to entity_id from the full tb Raise ValueError is entity_id cannot be parsed by TagSetTyping.type_parts_of. Raise KeyError if there is no UsesTagSets instance for the zone.

PlayOnAPI.cdsurl_data(self, suburl, method='GET', headers=None, **kw): Wrapper for suburl_data using CDS_BASE as the base URL.

PlayOnAPI.download(self, download_id: int, filename=None, *, quiet: bool, runstate: Optional[cs.resources.RunState] = <function uses_runstate.<locals>.<lambda> at 0x10e6c3ce0>, verbose: bool): Download the file with download_id to filename_basis. Return the TagSet for the recording.

The default filename is the basename of the filename from the download. If the filename is supplied with a trailing dot ('.') then the file extension will be taken from the filename of the download URL.

PlayOnAPI.feature(self, feature_id): Return the feature SQLTags instance for feature_id.

PlayOnAPI.featured_image_url(self, feature_name: str): URL of the image for a featured show.

PlayOnAPI.features(self): Fetch the list of featured shows.

PlayOnAPI.fetch_recordings(self, *, verbose=False) -> set[cs.app.playon.Recording]: Return a set of the Recording instances for the available recordings. This makes an API request.

PlayOnAPI.from_playon_date(date_s) -> datetime.datetime: Return a timezone aware datetime from a PlayOn date/time value; The PlayOn API seems to use UTC date strings.

PlayOnAPI.jwt: The JWT token.

PlayOnAPI.login(self): Perform a login, return the resulting dict. Does not update the state of self.

PlayOnAPI.login_expiry: Expiry UNIX time for the login state.

PlayOnAPI.ls(self, recording_specs, *, format: str, long_mode=False): List the specified recordings.

PlayOnAPI.notifications(self): Return the notifications.

PlayOnAPI.queue(self): Return the TagSet instances for the queued recordings.

PlayOnAPI.recording_ids_from_str(self, arg): Convert a string to a list of recording ids.

PlayOnAPI.recordings(self): Yield the Recordings.

Note that this includes both recorded and queued items.

PlayOnAPI.renew_jwt(self): UNUSED

PlayOnAPI.service(self, service_id: str): Return the service SQLTags instance for service_id.

PlayOnAPI.services(self): Fetch the list of services.

PlayOnAPI.suburl(self, suburl, *, api_version=None, headers=None, base_url=None, **kw): Override HTTPServiceAPI.suburl with default headers={'Authorization':self.jwt}.

  • class PlayOnCommand(cs.cmdutils.BaseCommand): Playon command line implementation.

    Usage summary:

    Usage: playon [common-options...] subcommand [args...]
    
      Environment:
        PLAYON_USER               PlayOn login name, default from $EMAIL.
        PLAYON_PASSWORD           PlayOn password.
                                  This is obtained from .netrc if omitted.
        PLAYON_FILENAME_FORMAT  Format string for downloaded filenames.
                                  Default: {series_prefix}{series_episode_name}--{resolution}--{playon.ProviderID}--playon--{playon.ID}
        PLAYON_TAGS_DBURL         Location of state tags database.
                                  Default: ~/var/playon.sqlite
    
      Recording specification:
        an int        The specific recording id.
        all           All known recordings.
        downloaded    Recordings already downloaded.
        expired       Recording which are no longer available.
        pending       Recordings not already downloaded.
        /regexp       Recordings whose Series or Name match the regexp,
                      case insensitive.
      Subcommands:
        account [common-options...]
          Report account state.
        api [common-options...] suburl
          GET suburl via the API, print result.
        cds [common-options...] suburl
          GET suburl via the content delivery API, print result.
          Example subpaths:
            content
            content/provider-name
        dl [common-options...] [recordings...]
          Download the specified recordings, default "pending".
          Options:
            -j dl-jobs  Concurrent download jobs.
        downloaded [common-options...] recordings...
          Mark the specified recordings as downloaded and no longer pending.
        feature [common-options...] [feature_id]
          List features.
          Options:
            -l  Long mode.
        help [common-options...] [-l] [-s] [subcommand-names...]
          Print help for subcommands.
          This outputs the full help for the named subcommands,
          or the short help for all subcommands if no names are specified.
          Options:
            -l  Long listing.
            -r  Recurse into subcommands.
            -s  Short listing.
        info [common-options...] [field-names...]
          Recite general information.
          Explicit field names may be provided to override the default listing.
        ls [common-options...] [recordings...]
          List available downloads.
          Options:
            -l            Long listing: list tags below each entry.
            -o ls-format  Format string for each entry. Default format:
                          {playon.ID} {playon.HumanSize} {resolution} {nice_name} {playon.ProviderID} {status:upper}
        poll [common-options...] [options...]
        q [common-options...] [recordings...]
          List queued recordings.
          Options:
            -l               Long listing: list tags below each entry.
            -o queue-format  Format string for each entry. Default format:
                             {playon.ID} {playon.Series} {playon.Name} {playon.ProviderID}
        queue [common-options...] [recordings...]
          List queued recordings.
          Options:
            -l               Long listing: list tags below each entry.
            -o queue-format  Format string for each entry. Default format:
                             {playon.ID} {playon.Series} {playon.Name} {playon.ProviderID}
        refresh [common-options...] [queue] [recordings]
          Update the db state from the PlayOn service.
        rename [common-options...] [-o filename_format] filenames...
          Rename the filenames according to their fstags.
          -n    No action, dry run.
          -o filename_format
                Format for the new filename, default '{series_prefix}{series_episode_name}--{resolution}--{playon.ProviderID}--playon--{playon.ID}'.
          Options:
            -o filename-format  Filename format.
        repl [common-options...]
          Run a REPL (Read Evaluate Print Loop), an interactive Python prompt.
          Options:
            --banner banner  Banner.
        service [common-options...] [service_id]
          List services.
        shell [common-options...]
          Run a command prompt via cmd.Cmd using this command's subcommands.
    

PlayOnCommand.Options

PlayOnCommand.cmd_account(self, argv): Usage: {cmd} Report account state.

PlayOnCommand.cmd_api(self, argv): Usage: {cmd} suburl GET suburl via the API, print result.

PlayOnCommand.cmd_cds(self, argv): Usage: {cmd} suburl GET suburl via the content delivery API, print result. Example subpaths: content content/provider-name

PlayOnCommand.cmd_dl(self, argv): Usage: {cmd} [recordings...] Download the specified recordings, default "pending". Options: -j dl-jobs Concurrent download jobs.

PlayOnCommand.cmd_downloaded(self, argv, locale='en_US'): Usage: {cmd} recordings... Mark the specified recordings as downloaded and no longer pending.

PlayOnCommand.cmd_feature(self, argv, locale='en_US'): Usage: {cmd} [feature_id] List features. Options: -l Long mode.

PlayOnCommand.cmd_ls(self, argv): Usage: {cmd} [recordings...] List available downloads. Options: -l Long listing: list tags below each entry. -o ls-format Format string for each entry. Default format: {LS_FORMAT}

PlayOnCommand.cmd_q(self, argv): Usage: {cmd} [recordings...] List queued recordings. Options: -l Long listing: list tags below each entry. -o queue-format Format string for each entry. Default format: {QUEUE_FORMAT}

PlayOnCommand.cmd_queue(self, argv): Usage: {cmd} [recordings...] List queued recordings. Options: -l Long listing: list tags below each entry. -o queue-format Format string for each entry. Default format: {QUEUE_FORMAT}

PlayOnCommand.cmd_refresh(self, argv): Usage: {cmd} [queue] [recordings] Update the db state from the PlayOn service.

PlayOnCommand.cmd_rename(self, argv, *, fstags: Optional[cs.fstags.FSTags] = <function <lambda> at 0x10cfa7a60>): Usage: {cmd} [-o filename_format] filenames... Rename the filenames according to their fstags. -n No action, dry run. -o filename_format Format for the new filename, default {DEFAULT_FILENAME_FORMAT!r}. Options: -o filename-format Filename format.

PlayOnCommand.cmd_service(self, argv, locale='en_US'): Usage: {cmd} [service_id] List services.

PlayOnCommand.run_context(self): Prepare the PlayOnAPI around each command invocation.

  • class PlayonSeriesEpisodeInfo(cs.mediainfo.SeriesEpisodeInfo): A SeriesEpisodeInfo with a from_Recording() factory method to build one from a PlayOn Recording instead or other mapping with playon.* keys.

PlayonSeriesEpisodeInfo.from_Recording(R: Mapping[str, Any]): Infer series episode information from a Recording or any mapping with ".playon.*" keys.

  • class PlayOnSQLTags(cs.sqltags.SQLTags): PlayOn flavoured SQLTags; it just has custom values for the default db location.
  • class Recording(_PlayOnEntity): A PlayOn recording.

Recording.filename(self, filename_format=None) -> str: Return the computed filename per filename_format, default from DEFAULT_FILENAME_FORMAT: '{series_prefix}{series_episode_name}--{resolution}--{playon.ProviderID}--playon--{playon.ID}'.

Recording.is_available(self): Is a recording available for download?

Recording.is_downloaded(self): Test whether this recording has been downloaded based on the presence of a download_path Tag or a true downloaded Tag.

Recording.is_expired(self): Test whether this recording is expired, which implies that it is no longer available for download.

Recording.is_pending(self): A pending download: available and not already downloaded.

Recording.is_queued(self): Is a recording still in the queue?

Recording.ls(self, *, format=None, long_mode=False, print_func=None): List a recording.

Recording.nice_name(self): A nice name for the recording: the PlayOn series and name, omitting the series if that is None.

Recording.recording_id(self): The recording id or None.

Recording.refresh_needed(self, **kw): Override for Refreshable.refresh_needed which always returns False for expired recordings.

Recording.resolution(self): The recording resolution derived from the quality via the Recording.RECORDING_QUALITY mapping.

Recording.series_prefix(self): Return a series prefix for recording containing the series name and season and episode, or ''.

Recording.status(self): Return a short status string.

Release Log

Release 20260531:

  • DOwnloads: use cs.rfc2616.content_length to get the download content-length, open the download file with 'xb'.
  • PlayOnAPI is now the source of the sqltags, do not expect to access it outside.
  • New _PlayOnEntity(HasSQLTags) base class for Recording and LoginState.
  • PlayOnAPI: new .login_userid property for external use.
  • PlayOnAPI.getitem: an int index is promoted to ('recording,str(index)) for lookup.
  • PlayOnAPI: new .recordings() finding playon.recording.*; use it for iter.
  • PlayOnAPI: new .recording_ids_from_str() method for use by the CLI.
  • PlayOnAPI: use the new UsesTagSets stuff.
  • The PlayOn API has started reciting times with a microsecond field.
  • PlayOnAPI.from_playon_date: accomodate time formats with and without microseconds.
  • Recording.STALE_AGE -> Recording.refresh_lifespan for Refreshable.
  • PlayOnCommand.cmd_dl: use pmap() to run the downloads in parallel.
  • Assorted other internal changes.

Release 20241007: Make things more cancellable.

Release 20240723:

  • Replace many raises of RuntimeError with NotImplementedError, suggestion by @dimaqq on discuss.python.org.
  • This update tracks some bugfixes in some required modules.

Release 20240522: New superior tv-series/season/episode inference.

Release 20240316: Fixed release upload artifacts.

Release 20240201.1: Release with "playon" script.

Release 20240201:

  • PlayOnCommand.cmd_dl: collapse dashes more reliably, restore the space squashing, make the downloads interruptable.
  • PlayOnCommand._list: sort each listing argument by recording id.

Release 20230705: DEFAULT_FILENAME_FORMAT: replace naive playon.Name with series_episode_name which is the name with leading series/episode info removed, honour in "playon dl".

Release 20230703:

  • PlayOnAPI: features, feature, featured_image_url, service_image_url.
  • PlayOnCommand: new cmd_feature like cmd_service but for featured shows.
  • PlayOnAPI.suburl: infer _base_url from api_version if _base_url is None and api_version is provided.
  • Recording.is_downloaded: also check for a 'downloaded' tag, fallback for when the downloaded_path is empty.
  • PlayOnCommand.cmd_downloaded: add 'downloaded" tag to specified recordings.

Release 20230217:

  • Move some core stuff off into cs.service_api.HTTPServiceAPI.
  • Move core Recording.is_stale() method to TagSet.is_stale(), leave override method behind.
  • Persist login tokens in a db for reuse while still fresh.
  • "playon dl": allow interrupting downloads.
  • Cleaner handling of playon.Name having a leading SNNeNN prefix.

Release 20221228:

  • PlayOnAPI.suburl_data: progress reporting, raise on bad response, upgrade JSON error warning.
  • PlayOnAPI: use a common cookie jar across API calls.
  • PlayOnCommand: new "api" and "cds" API access subcommands.
  • PlayOnCommand._refresh_sqltags_data: bugfix "expired cache" logic.
  • PlayOnCommand: new "poll" subcommand reporting the API notifications response.

Release 20220311: Bugfix criteria for refreshing the PlayOn state.

Release 20211212: Initial release.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

cs_app_playon-20260531.tar.gz (19.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

cs_app_playon-20260531-py2.py3-none-any.whl (17.4 kB view details)

Uploaded Python 2Python 3

File details

Details for the file cs_app_playon-20260531.tar.gz.

File metadata

  • Download URL: cs_app_playon-20260531.tar.gz
  • Upload date:
  • Size: 19.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.1

File hashes

Hashes for cs_app_playon-20260531.tar.gz
Algorithm Hash digest
SHA256 71f29bdfe15583fbbcb2677074a885ec58c4bac9a5a594055b8a5c069a769629
MD5 d87625e1ac6740827b2a221eeab953b7
BLAKE2b-256 83a069c309e9c0091943eaee2c97b9948a2efc8bfc662ccddab54836ebb47fba

See more details on using hashes here.

File details

Details for the file cs_app_playon-20260531-py2.py3-none-any.whl.

File metadata

File hashes

Hashes for cs_app_playon-20260531-py2.py3-none-any.whl
Algorithm Hash digest
SHA256 a20249d95514f97e6b28b18ff433194b2c6c397ed16216fb698fb39c315cf233
MD5 921ebca486e1b5a27d1f5f73eb9a064c
BLAKE2b-256 a07a4b722af0c83010bab1a3f9328ef648abd8fda3483ba702b64b0aaf3d5233

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page