pax_global_header00006660000000000000000000000064137526650240014524gustar00rootroot0000000000000052 comment=861fc49e74c34c8f04e1495d0e285884b130ab47 jjlawren-python-plexauth-861fc49/000077500000000000000000000000001375266502400170555ustar00rootroot00000000000000jjlawren-python-plexauth-861fc49/.gitignore000066400000000000000000000001041375266502400210400ustar00rootroot00000000000000**/__pycache__/ *.pyc plexauth.egg-info # Build files build/ dist/ jjlawren-python-plexauth-861fc49/LICENSE000066400000000000000000000020511375266502400200600ustar00rootroot00000000000000MIT License Copyright (c) 2019 jjlawren Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. jjlawren-python-plexauth-861fc49/README.md000066400000000000000000000015761375266502400203450ustar00rootroot00000000000000# python-plexauth Handles the authorization flow to obtain tokens from Plex.tv via external redirection. Example usage: ``` import asyncio from plexauth import PlexAuth PAYLOAD = { 'X-Plex-Product': 'Test Product', 'X-Plex-Version': '0.0.1', 'X-Plex-Device': 'Test Device', 'X-Plex-Platform': 'Test Platform', 'X-Plex-Device-Name': 'Test Device Name', 'X-Plex-Device-Vendor': 'Test Vendor', 'X-Plex-Model': 'Test Model', 'X-Plex-Client-Platform': 'Test Client Platform' } async def main(): async with PlexAuth(PAYLOAD) as plexauth: await plexauth.initiate_auth() print("Complete auth at URL: {}".format(plexauth.auth_url())) token = await plexauth.token() if token: print("Token: {}".format(token)) else: print("No token returned.") loop = asyncio.get_event_loop() loop.run_until_complete(main()) ``` jjlawren-python-plexauth-861fc49/plexauth.py000077500000000000000000000054111375266502400212650ustar00rootroot00000000000000"""Handle a Plex.tv authorization flow to obtain an access token.""" import aiohttp from asyncio import sleep from datetime import datetime, timedelta import urllib.parse import uuid __version__ = '0.0.5' CODES_URL = 'https://plex.tv/api/v2/pins.json?strong=true' AUTH_URL = 'https://app.plex.tv/auth#!?{}' TOKEN_URL = 'https://plex.tv/api/v2/pins/{}' class PlexAuth(): def __init__(self, payload, session=None, headers=None): '''Create PlexAuth instance.''' self.client_identifier = str(uuid.uuid4()) self._code = None self._headers = headers self._identifier = None self._payload = payload self._payload['X-Plex-Client-Identifier'] = self.client_identifier self._local_session = False self._session = session if session is None: self._session = aiohttp.ClientSession() self._local_session = True async def initiate_auth(self): '''Request codes needed to create an auth URL. Starts external timeout.''' async with self._session.post(CODES_URL, data=self._payload, headers=self._headers) as resp: response = await resp.json() self._code = response['code'] self._identifier = response['id'] def auth_url(self, forward_url=None): '''Return an auth URL for the user to follow.''' parameters = { 'clientID': self.client_identifier, 'code': self._code, } if forward_url: parameters['forwardUrl'] = forward_url url = AUTH_URL.format(urllib.parse.urlencode(parameters)) return url async def request_auth_token(self): '''Request an auth token from Plex.''' token_url = TOKEN_URL.format(self._code) payload = dict(self._payload) payload['Accept'] = 'application/json' async with self._session.get(TOKEN_URL.format(self._identifier), headers=payload) as resp: response = await resp.json() token = response['authToken'] return token async def token(self, timeout=60): '''Poll Plex endpoint until a token is retrieved or times out.''' token = None wait_until = datetime.now() + timedelta(seconds=timeout) break_loop = False while not break_loop: await sleep(3) token = await self.request_auth_token() if token or wait_until < datetime.now(): break_loop = True return token async def close(self): """Close open client session.""" if self._local_session: await self._session.close() async def __aenter__(self): """Async enter.""" return self async def __aexit__(self, *exc_info): """Async exit.""" await self.close() jjlawren-python-plexauth-861fc49/setup.py000066400000000000000000000015411375266502400205700ustar00rootroot00000000000000from setuptools import setup with open('README.md') as f: long_description = f.read() VERSION="0.0.6" setup( name='plexauth', version=VERSION, description='Handles the authorization flow to obtain tokens from Plex.tv via external redirection.', long_description=long_description, long_description_content_type='text/markdown', url='https://github.com/jjlawren/python-plexauth/', license='MIT', author='Jason Lawrence', author_email='jjlawren@users.noreply.github.com', platforms='any', py_modules=['plexauth'], install_requires=['aiohttp'], classifiers=[ 'License :: OSI Approved :: MIT License', 'Operating System :: OS Independent', 'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', ] )