Plex plugin to to play various online streams (mostly Latvian).

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. # DumbTools for Plex v1.1 by Cory <babylonstudio@gmail.com>
  2. import urllib2
  3. class DumbKeyboard:
  4. clients = ['Plex for iOS', 'Plex Media Player', 'Plex Web']
  5. KEYS = list('abcdefghijklmnopqrstuvwxyz1234567890-=;[]\\\',./')
  6. SHIFT_KEYS = list('ABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()_+:{}|\"<>?')
  7. def __init__(self, prefix, oc, callback, dktitle=None, dkthumb=None,
  8. dkplaceholder=None, dksecure=False, **kwargs):
  9. cb_hash = hash(str(callback)+str(kwargs))
  10. Route.Connect(prefix+'/dumbkeyboard/%s'%cb_hash, self.Keyboard)
  11. Route.Connect(prefix+'/dumbkeyboard/%s/submit'%cb_hash, self.Submit)
  12. Route.Connect(prefix+'/dumbkeyboard/%s/history'%cb_hash, self.History)
  13. Route.Connect(prefix+'/dumbkeyboard/%s/history/clear'%cb_hash, self.ClearHistory)
  14. Route.Connect(prefix+'/dumbkeyboard/%s/history/add/{query}'%cb_hash, self.AddHistory)
  15. # Add our directory item
  16. oc.add(DirectoryObject(key=Callback(self.Keyboard, query=dkplaceholder),
  17. title=str(dktitle) if dktitle else \
  18. u'%s'%L('DumbKeyboard Search'),
  19. thumb=dkthumb))
  20. # establish our dict entry
  21. if 'DumbKeyboard-History' not in Dict:
  22. Dict['DumbKeyboard-History'] = []
  23. Dict.Save()
  24. self.Callback = callback
  25. self.callback_args = kwargs
  26. self.secure = dksecure
  27. def Keyboard(self, query=None, shift=False):
  28. if self.secure and query is not None:
  29. string = ''.join(['*' for i in range(len(query[:-1]))]) + query[-1]
  30. else:
  31. string = query if query else ""
  32. oc = ObjectContainer()
  33. # Submit
  34. oc.add(DirectoryObject(key=Callback(self.Submit, query=query),
  35. title=u'%s: %s'%(L('Submit'), string.replace(' ', '_'))))
  36. # Search History
  37. if Dict['DumbKeyboard-History']:
  38. oc.add(DirectoryObject(key=Callback(self.History),
  39. title=u'%s'%L('Search History')))
  40. # Space
  41. oc.add(DirectoryObject(key=Callback(self.Keyboard,
  42. query=query+" " if query else " "),
  43. title='Space'))
  44. # Backspace (not really needed since you can just hit back)
  45. if query is not None:
  46. oc.add(DirectoryObject(key=Callback(self.Keyboard, query=query[:-1]),
  47. title='Backspace'))
  48. # Shift
  49. oc.add(DirectoryObject(key=Callback(self.Keyboard, query=query, shift=True),
  50. title='Shift'))
  51. # Keys
  52. for key in self.KEYS if not shift else self.SHIFT_KEYS:
  53. oc.add(DirectoryObject(key=Callback(self.Keyboard,
  54. query=query+key if query else key),
  55. title=u'%s'%key))
  56. return oc
  57. def History(self):
  58. oc = ObjectContainer()
  59. if Dict['DumbKeyboard-History']:
  60. oc.add(DirectoryObject(key=Callback(self.ClearHistory),
  61. title=u'%s'%L('Clear History')))
  62. for item in Dict['DumbKeyboard-History']:
  63. oc.add(DirectoryObject(key=Callback(self.Submit, query=item),
  64. title=u'%s'%item))
  65. return oc
  66. def ClearHistory(self):
  67. Dict['DumbKeyboard-History'] = []
  68. Dict.Save()
  69. return self.History()
  70. def AddHistory(self, query):
  71. if query not in Dict['DumbKeyboard-History']:
  72. Dict['DumbKeyboard-History'].append(query)
  73. Dict.Save()
  74. def Submit(self, query):
  75. self.AddHistory(query)
  76. kwargs = {'query': query}
  77. kwargs.update(self.callback_args)
  78. return self.Callback(**kwargs)
  79. class DumbPrefs:
  80. clients = ['Plex for iOS', 'Plex Media Player', 'Plex Home Theater',
  81. 'OpenPHT', 'Plex for Roku']
  82. def __init__(self, prefix, oc, title=None, thumb=None):
  83. self.host = 'http://127.0.0.1:32400'
  84. try:
  85. self.CheckAuth()
  86. except Exception as e:
  87. Log.Error('DumbPrefs: this user cant access prefs: %s' % str(e))
  88. return
  89. Route.Connect(prefix+'/dumbprefs/list', self.ListPrefs)
  90. Route.Connect(prefix+'/dumbprefs/listenum', self.ListEnum)
  91. Route.Connect(prefix+'/dumbprefs/set', self.Set)
  92. Route.Connect(prefix+'/dumbprefs/settext', self.SetText)
  93. oc.add(DirectoryObject(key=Callback(self.ListPrefs),
  94. title=title if title else L('Preferences'),
  95. thumb=thumb))
  96. self.prefix = prefix
  97. self.GetPrefs()
  98. def GetHeaders(self):
  99. headers = Request.Headers
  100. headers['Connection'] = 'close'
  101. return headers
  102. def CheckAuth(self):
  103. """ Only the main users token is accepted at /myplex/account """
  104. headers = {'X-Plex-Token': Request.Headers.get('X-Plex-Token', '')}
  105. req = urllib2.Request("%s/myplex/account" % self.host, headers=headers)
  106. res = urllib2.urlopen(req)
  107. def GetPrefs(self):
  108. data = HTTP.Request("%s/:/plugins/%s/prefs" % (self.host, Plugin.Identifier),
  109. headers=self.GetHeaders())
  110. prefs = XML.ElementFromString(data).xpath('/MediaContainer/Setting')
  111. self.prefs = [{'id': pref.xpath("@id")[0],
  112. 'type': pref.xpath("@type")[0],
  113. 'label': pref.xpath("@label")[0],
  114. 'default': pref.xpath("@default")[0],
  115. 'secure': True if pref.xpath("@secure")[0] == "true" else False,
  116. 'values': pref.xpath("@values")[0].split("|") \
  117. if pref.xpath("@values") else None
  118. } for pref in prefs]
  119. def Set(self, key, value):
  120. HTTP.Request("%s/:/plugins/%s/prefs/set?%s=%s" % (self.host,
  121. Plugin.Identifier,
  122. key, value),
  123. headers=self.GetHeaders(),
  124. immediate=True)
  125. return ObjectContainer()
  126. def ListPrefs(self):
  127. oc = ObjectContainer(no_cache=True)
  128. for pref in self.prefs:
  129. do = DirectoryObject()
  130. value = Prefs[pref['id']] if not pref['secure'] else \
  131. ''.join(['*' for i in range(len(Prefs[pref['id']]))])
  132. title = u'%s: %s = %s' % (L(pref['label']), pref['type'], L(value))
  133. if pref['type'] == 'enum':
  134. do.key = Callback(self.ListEnum, id=pref['id'])
  135. elif pref['type'] == 'bool':
  136. do.key = Callback(self.Set, key=pref['id'],
  137. value=str(not Prefs[pref['id']]).lower())
  138. elif pref['type'] == 'text':
  139. if Client.Product in DumbKeyboard.clients:
  140. DumbKeyboard(self.prefix, oc, self.SetText,
  141. id=pref['id'],
  142. dktitle=title,
  143. dkplaceholder=Prefs[pref['id']],
  144. dksecure=pref['secure'])
  145. else:
  146. oc.add(InputDirectoryObject(key=Callback(self.SetText, id=pref['id']),
  147. title=title))
  148. continue
  149. else:
  150. do.key = Callback(self.ListPrefs)
  151. do.title = title
  152. oc.add(do)
  153. return oc
  154. def ListEnum(self, id):
  155. oc = ObjectContainer()
  156. for pref in self.prefs:
  157. if pref['id'] == id:
  158. for i, option in enumerate(pref['values']):
  159. oc.add(DirectoryObject(key=Callback(self.Set, key=id, value=i),
  160. title=u'%s'%option))
  161. return oc
  162. def SetText(self, query, id):
  163. return self.Set(key=id, value=query)