91 lines
2.6 KiB
Python
91 lines
2.6 KiB
Python
|
# -*- coding: utf-8 -*-
|
||
|
import util
|
||
|
import http
|
||
|
from threading import Thread
|
||
|
from xml.etree import ElementTree
|
||
|
import time
|
||
|
|
||
|
import exceptions
|
||
|
|
||
|
import video
|
||
|
import audio
|
||
|
import photo
|
||
|
|
||
|
video, audio, photo # Hides warning message
|
||
|
|
||
|
|
||
|
class PinLogin(object):
|
||
|
INIT = 'https://plex.tv/pins.xml'
|
||
|
POLL = 'https://plex.tv/pins/{0}.xml'
|
||
|
POLL_INTERVAL = 1
|
||
|
|
||
|
def __init__(self, callback=None):
|
||
|
self._callback = callback
|
||
|
self.id = None
|
||
|
self.pin = None
|
||
|
self.authenticationToken = None
|
||
|
self._finished = False
|
||
|
self._abort = False
|
||
|
self._expired = False
|
||
|
self._init()
|
||
|
|
||
|
def _init(self):
|
||
|
response = http.POST(self.INIT)
|
||
|
if response.status_code != http.codes.created:
|
||
|
codename = http.status_codes.get(response.status_code)[0]
|
||
|
raise exceptions.BadRequest('({0}) {1}'.format(response.status_code, codename))
|
||
|
data = ElementTree.fromstring(response.text.encode('utf-8'))
|
||
|
self.pin = data.find('code').text
|
||
|
self.id = data.find('id').text
|
||
|
|
||
|
def _poll(self):
|
||
|
try:
|
||
|
start = time.time()
|
||
|
while not self._abort and time.time() - start < 300:
|
||
|
try:
|
||
|
response = http.GET(self.POLL.format(self.id))
|
||
|
except Exception, e:
|
||
|
util.ERROR('PinLogin connection error: {0}'.format(e.__class__), err=e)
|
||
|
time.sleep(self.POLL_INTERVAL)
|
||
|
continue
|
||
|
|
||
|
if response.status_code != http.codes.ok:
|
||
|
self._expired = True
|
||
|
break
|
||
|
try:
|
||
|
data = ElementTree.fromstring(response.text.encode('utf-8'))
|
||
|
except Exception, e:
|
||
|
util.ERROR('PinLogin data error: {0}'.format(e.__class__), err=e)
|
||
|
time.sleep(self.POLL_INTERVAL)
|
||
|
continue
|
||
|
|
||
|
token = data.find('auth_token').text
|
||
|
if token:
|
||
|
self.authenticationToken = token
|
||
|
break
|
||
|
time.sleep(self.POLL_INTERVAL)
|
||
|
|
||
|
if self._callback:
|
||
|
self._callback(self.authenticationToken)
|
||
|
finally:
|
||
|
self._finished = True
|
||
|
|
||
|
def finished(self):
|
||
|
return self._finished
|
||
|
|
||
|
def expired(self):
|
||
|
return self._expired
|
||
|
|
||
|
def startTokenPolling(self):
|
||
|
t = Thread(target=self._poll, name='PIN-LOGIN:Token-Poll')
|
||
|
t.start()
|
||
|
return t
|
||
|
|
||
|
def waitForToken(self):
|
||
|
t = self.startTokenPolling()
|
||
|
t.join()
|
||
|
return self.authenticationToken
|
||
|
|
||
|
def abort(self):
|
||
|
self._abort = True
|