# DumbTools for Plex v1.1 by Cory import urllib2 class DumbKeyboard: clients = ['Plex for iOS', 'Plex Media Player', 'Plex Web'] KEYS = list('abcdefghijklmnopqrstuvwxyz1234567890-=;[]\\\',./') SHIFT_KEYS = list('ABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()_+:{}|\"<>?') def __init__(self, prefix, oc, callback, dktitle=None, dkthumb=None, dkplaceholder=None, dksecure=False, **kwargs): cb_hash = hash(str(callback)+str(kwargs)) Route.Connect(prefix+'/dumbkeyboard/%s'%cb_hash, self.Keyboard) Route.Connect(prefix+'/dumbkeyboard/%s/submit'%cb_hash, self.Submit) Route.Connect(prefix+'/dumbkeyboard/%s/history'%cb_hash, self.History) Route.Connect(prefix+'/dumbkeyboard/%s/history/clear'%cb_hash, self.ClearHistory) Route.Connect(prefix+'/dumbkeyboard/%s/history/add/{query}'%cb_hash, self.AddHistory) # Add our directory item oc.add(DirectoryObject(key=Callback(self.Keyboard, query=dkplaceholder), title=str(dktitle) if dktitle else \ u'%s'%L('DumbKeyboard Search'), thumb=dkthumb)) # establish our dict entry if 'DumbKeyboard-History' not in Dict: Dict['DumbKeyboard-History'] = [] Dict.Save() self.Callback = callback self.callback_args = kwargs self.secure = dksecure def Keyboard(self, query=None, shift=False): if self.secure and query is not None: string = ''.join(['*' for i in range(len(query[:-1]))]) + query[-1] else: string = query if query else "" oc = ObjectContainer() # Submit oc.add(DirectoryObject(key=Callback(self.Submit, query=query), title=u'%s: %s'%(L('Submit'), string.replace(' ', '_')))) # Search History if Dict['DumbKeyboard-History']: oc.add(DirectoryObject(key=Callback(self.History), title=u'%s'%L('Search History'))) # Space oc.add(DirectoryObject(key=Callback(self.Keyboard, query=query+" " if query else " "), title='Space')) # Backspace (not really needed since you can just hit back) if query is not None: oc.add(DirectoryObject(key=Callback(self.Keyboard, query=query[:-1]), title='Backspace')) # Shift oc.add(DirectoryObject(key=Callback(self.Keyboard, query=query, shift=True), title='Shift')) # Keys for key in self.KEYS if not shift else self.SHIFT_KEYS: oc.add(DirectoryObject(key=Callback(self.Keyboard, query=query+key if query else key), title=u'%s'%key)) return oc def History(self): oc = ObjectContainer() if Dict['DumbKeyboard-History']: oc.add(DirectoryObject(key=Callback(self.ClearHistory), title=u'%s'%L('Clear History'))) for item in Dict['DumbKeyboard-History']: oc.add(DirectoryObject(key=Callback(self.Submit, query=item), title=u'%s'%item)) return oc def ClearHistory(self): Dict['DumbKeyboard-History'] = [] Dict.Save() return self.History() def AddHistory(self, query): if query not in Dict['DumbKeyboard-History']: Dict['DumbKeyboard-History'].append(query) Dict.Save() def Submit(self, query): self.AddHistory(query) kwargs = {'query': query} kwargs.update(self.callback_args) return self.Callback(**kwargs) class DumbPrefs: clients = ['Plex for iOS', 'Plex Media Player', 'Plex Home Theater', 'OpenPHT', 'Plex for Roku'] def __init__(self, prefix, oc, title=None, thumb=None): self.host = 'http://127.0.0.1:32400' try: self.CheckAuth() except Exception as e: Log.Error('DumbPrefs: this user cant access prefs: %s' % str(e)) return Route.Connect(prefix+'/dumbprefs/list', self.ListPrefs) Route.Connect(prefix+'/dumbprefs/listenum', self.ListEnum) Route.Connect(prefix+'/dumbprefs/set', self.Set) Route.Connect(prefix+'/dumbprefs/settext', self.SetText) oc.add(DirectoryObject(key=Callback(self.ListPrefs), title=title if title else L('Preferences'), thumb=thumb)) self.prefix = prefix self.GetPrefs() def GetHeaders(self): headers = Request.Headers headers['Connection'] = 'close' return headers def CheckAuth(self): """ Only the main users token is accepted at /myplex/account """ headers = {'X-Plex-Token': Request.Headers.get('X-Plex-Token', '')} req = urllib2.Request("%s/myplex/account" % self.host, headers=headers) res = urllib2.urlopen(req) def GetPrefs(self): data = HTTP.Request("%s/:/plugins/%s/prefs" % (self.host, Plugin.Identifier), headers=self.GetHeaders()) prefs = XML.ElementFromString(data).xpath('/MediaContainer/Setting') self.prefs = [{'id': pref.xpath("@id")[0], 'type': pref.xpath("@type")[0], 'label': pref.xpath("@label")[0], 'default': pref.xpath("@default")[0], 'secure': True if pref.xpath("@secure")[0] == "true" else False, 'values': pref.xpath("@values")[0].split("|") \ if pref.xpath("@values") else None } for pref in prefs] def Set(self, key, value): HTTP.Request("%s/:/plugins/%s/prefs/set?%s=%s" % (self.host, Plugin.Identifier, key, value), headers=self.GetHeaders(), immediate=True) return ObjectContainer() def ListPrefs(self): oc = ObjectContainer(no_cache=True) for pref in self.prefs: do = DirectoryObject() value = Prefs[pref['id']] if not pref['secure'] else \ ''.join(['*' for i in range(len(Prefs[pref['id']]))]) title = u'%s: %s = %s' % (L(pref['label']), pref['type'], L(value)) if pref['type'] == 'enum': do.key = Callback(self.ListEnum, id=pref['id']) elif pref['type'] == 'bool': do.key = Callback(self.Set, key=pref['id'], value=str(not Prefs[pref['id']]).lower()) elif pref['type'] == 'text': if Client.Product in DumbKeyboard.clients: DumbKeyboard(self.prefix, oc, self.SetText, id=pref['id'], dktitle=title, dkplaceholder=Prefs[pref['id']], dksecure=pref['secure']) else: oc.add(InputDirectoryObject(key=Callback(self.SetText, id=pref['id']), title=title)) continue else: do.key = Callback(self.ListPrefs) do.title = title oc.add(do) return oc def ListEnum(self, id): oc = ObjectContainer() for pref in self.prefs: if pref['id'] == id: for i, option in enumerate(pref['values']): oc.add(DirectoryObject(key=Callback(self.Set, key=id, value=i), title=u'%s'%option)) return oc def SetText(self, query, id): return self.Set(key=id, value=query)