code time
This commit is contained in:
		
							parent
							
								
									789a5e0b02
								
							
						
					
					
						commit
						ae28da8d60
					
				
					 153 changed files with 56768 additions and 1 deletions
				
			
		
							
								
								
									
										50
									
								
								resources/lib/__init__.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								resources/lib/__init__.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,50 @@ | |||
| import os | ||||
| import sys | ||||
| 
 | ||||
| sys.path.insert(1, os.path.join(os.path.dirname(__file__))) | ||||
| 
 | ||||
| # IMPORTANT: The 'cherrypy' module cannot be imported as a submodule from 'httpproxy.py'. | ||||
| #   I.e, 'from deps import cherrypy' will not work. Not sure why. So we do the following | ||||
| #   path hack to put 'cherrypy' on the module search path: | ||||
| sys.path.insert(1, os.path.join(os.path.dirname(__file__), "deps")) | ||||
| 
 | ||||
| 
 | ||||
| # import pkgutil | ||||
| 
 | ||||
| # def list_submodules(list_name, package_name): | ||||
| #     for loader, module_name, is_pkg in pkgutil.walk_packages( | ||||
| #         package_name.__path__, package_name.__name__ + "." | ||||
| #     ): | ||||
| #         list_name.append(module_name) | ||||
| #         print(f"module_name 1 = {module_name}, is_pkg = {is_pkg}.") | ||||
| #         try: | ||||
| #             module_name = __import__(module_name, fromlist="dummylist") | ||||
| #         except Exception as ex: | ||||
| #             print(ex) | ||||
| #             module_name = None | ||||
| #         print(f"module_name 2 = {module_name}.") | ||||
| #         if is_pkg: | ||||
| #             list_submodules(list_name, module_name) | ||||
| # | ||||
| # | ||||
| # if len(sys.argv) != 2: | ||||
| #     print("Usage: {} [PACKAGE-NAME]".format(os.path.basename(__file__))) | ||||
| #     sys.exit(1) | ||||
| # else: | ||||
| #     package_name = sys.argv[1] | ||||
| # | ||||
| # print(f"package_name = '{package_name}'.") | ||||
| # try: | ||||
| #     package = __import__(package_name) | ||||
| # except ImportError: | ||||
| #     print("Package {} not found...".format(package_name)) | ||||
| #     sys.exit(1) | ||||
| # | ||||
| # print(f"package.__path__ = '{package.__path__}'.") | ||||
| # print(f"package.__name__ = '{package.__name__}'.") | ||||
| # | ||||
| # all_modules = [] | ||||
| # list_submodules(all_modules, package) | ||||
| # | ||||
| # print(f"all_modules = {all_modules}.") | ||||
| # sys.exit(1) | ||||
							
								
								
									
										61
									
								
								resources/lib/bottle_manager.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								resources/lib/bottle_manager.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,61 @@ | |||
| from wsgiref.simple_server import make_server | ||||
| 
 | ||||
| from bottle import app, request, HTTPResponse, Bottle | ||||
| import xbmc | ||||
| 
 | ||||
| import re | ||||
| 
 | ||||
| from librespot.core import Session | ||||
| from librespot.audio.decoders import AudioQuality, VorbisOnlyAudioQuality | ||||
| from librespot.metadata import TrackId | ||||
| 
 | ||||
| from utils import log_msg | ||||
| 
 | ||||
| class LibrespotServer(Bottle): | ||||
|     def __init__(self, session: Session): | ||||
|         super(LibrespotServer, self).__init__() | ||||
|         self.session: Session = session | ||||
|         self.route('/track/<track_id>', callback=self.stream) | ||||
| 
 | ||||
|     # TODO: Make Range header work PLEASE I BEG | ||||
| 
 | ||||
|     def stream(self, track_id): | ||||
|         try: | ||||
|             playabletrack_id = TrackId.from_uri(f"spotify:track:{track_id}") | ||||
|             stream = self.session.content_feeder().load( | ||||
|                 playabletrack_id, VorbisOnlyAudioQuality(AudioQuality.NORMAL), False, | ||||
|                 None) | ||||
|             start = 0 | ||||
|             end = stream.input_stream.size | ||||
|             payload = stream.input_stream.stream() | ||||
|             log_msg(stream.input_stream.size) | ||||
|             # reqrange = request.get_header("range") | ||||
|             # if reqrange is not None: | ||||
|             #     range_search = re.search( | ||||
|             #         "^bytes=(?P<start>[0-9]+?)-(?P<end>[0-9]+?)$", | ||||
|             #         reqrange) | ||||
|             #     if range_search is not None: | ||||
|             #         start = int(range_search.group("start")) | ||||
|             #         end = (int(range_search.group("end")) | ||||
|             #                 if int(range_search.group("end")) <= | ||||
|             #                 stream.input_stream.size else | ||||
|             #                 stream.input_stream.size) | ||||
|             #         payload.skip(start) | ||||
|             #     else: | ||||
|             #         payload = stream | ||||
|             response = HTTPResponse(body=payload) | ||||
|             response.add_header('Content-Type', 'audio/ogg') | ||||
|             # response.add_header('Accept-Ranges', 'bytes') | ||||
|             # response.add_header("Content-Length", str(stream.input_stream.size).encode() if | ||||
|             #                 stream.input_stream.size == end else "{}-{}/{}" | ||||
|             #                 .format(start, end, | ||||
|             #                         stream.input_stream.size).encode()) | ||||
|             return response | ||||
|         except Exception as e: | ||||
|             log_msg(e) | ||||
| 
 | ||||
| def start_thread(web_port: int) -> None: | ||||
|     httpd = make_server('127.0.0.1', web_port, app) | ||||
|     monitor = xbmc.Monitor() | ||||
|     while not monitor.abortRequested(): | ||||
|         httpd.handle_request() | ||||
							
								
								
									
										154
									
								
								resources/lib/defusedxml/ElementTree.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										154
									
								
								resources/lib/defusedxml/ElementTree.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,154 @@ | |||
| # defusedxml | ||||
| # | ||||
| # Copyright (c) 2013 by Christian Heimes <christian@python.org> | ||||
| # Licensed to PSF under a Contributor Agreement. | ||||
| # See https://www.python.org/psf/license for licensing details. | ||||
| """Defused xml.etree.ElementTree facade | ||||
| """ | ||||
| from __future__ import print_function, absolute_import | ||||
| 
 | ||||
| import sys | ||||
| import warnings | ||||
| from xml.etree.ElementTree import ParseError | ||||
| from xml.etree.ElementTree import TreeBuilder as _TreeBuilder | ||||
| from xml.etree.ElementTree import parse as _parse | ||||
| from xml.etree.ElementTree import tostring | ||||
| 
 | ||||
| from .common import PY3 | ||||
| 
 | ||||
| if PY3: | ||||
|     import importlib | ||||
| else: | ||||
|     from xml.etree.ElementTree import XMLParser as _XMLParser | ||||
|     from xml.etree.ElementTree import iterparse as _iterparse | ||||
| 
 | ||||
| 
 | ||||
| from .common import ( | ||||
|     DTDForbidden, | ||||
|     EntitiesForbidden, | ||||
|     ExternalReferenceForbidden, | ||||
|     _generate_etree_functions, | ||||
| ) | ||||
| 
 | ||||
| __origin__ = "xml.etree.ElementTree" | ||||
| 
 | ||||
| 
 | ||||
| def _get_py3_cls(): | ||||
|     """Python 3.3 hides the pure Python code but defusedxml requires it. | ||||
| 
 | ||||
|     The code is based on test.support.import_fresh_module(). | ||||
|     """ | ||||
|     pymodname = "xml.etree.ElementTree" | ||||
|     cmodname = "_elementtree" | ||||
| 
 | ||||
|     pymod = sys.modules.pop(pymodname, None) | ||||
|     cmod = sys.modules.pop(cmodname, None) | ||||
| 
 | ||||
|     sys.modules[cmodname] = None | ||||
|     try: | ||||
|         pure_pymod = importlib.import_module(pymodname) | ||||
|     finally: | ||||
|         # restore module | ||||
|         sys.modules[pymodname] = pymod | ||||
|         if cmod is not None: | ||||
|             sys.modules[cmodname] = cmod | ||||
|         else: | ||||
|             sys.modules.pop(cmodname, None) | ||||
|         # restore attribute on original package | ||||
|         etree_pkg = sys.modules["xml.etree"] | ||||
|         if pymod is not None: | ||||
|             etree_pkg.ElementTree = pymod | ||||
|         elif hasattr(etree_pkg, "ElementTree"): | ||||
|             del etree_pkg.ElementTree | ||||
| 
 | ||||
|     _XMLParser = pure_pymod.XMLParser | ||||
|     _iterparse = pure_pymod.iterparse | ||||
|     # patch pure module to use ParseError from C extension | ||||
|     pure_pymod.ParseError = ParseError | ||||
| 
 | ||||
|     return _XMLParser, _iterparse | ||||
| 
 | ||||
| 
 | ||||
| if PY3: | ||||
|     _XMLParser, _iterparse = _get_py3_cls() | ||||
| 
 | ||||
| 
 | ||||
| _sentinel = object() | ||||
| 
 | ||||
| 
 | ||||
| class DefusedXMLParser(_XMLParser): | ||||
|     def __init__( | ||||
|         self, | ||||
|         html=_sentinel, | ||||
|         target=None, | ||||
|         encoding=None, | ||||
|         forbid_dtd=False, | ||||
|         forbid_entities=True, | ||||
|         forbid_external=True, | ||||
|     ): | ||||
|         # Python 2.x old style class | ||||
|         _XMLParser.__init__(self, target=target, encoding=encoding) | ||||
|         if html is not _sentinel: | ||||
|             # the 'html' argument has been deprecated and ignored in all | ||||
|             # supported versions of Python. Python 3.8 finally removed it. | ||||
|             if html: | ||||
|                 raise TypeError("'html=True' is no longer supported.") | ||||
|             else: | ||||
|                 warnings.warn( | ||||
|                     "'html' keyword argument is no longer supported. Pass " | ||||
|                     "in arguments as keyword arguments.", | ||||
|                     category=DeprecationWarning, | ||||
|                 ) | ||||
| 
 | ||||
|         self.forbid_dtd = forbid_dtd | ||||
|         self.forbid_entities = forbid_entities | ||||
|         self.forbid_external = forbid_external | ||||
|         if PY3: | ||||
|             parser = self.parser | ||||
|         else: | ||||
|             parser = self._parser | ||||
|         if self.forbid_dtd: | ||||
|             parser.StartDoctypeDeclHandler = self.defused_start_doctype_decl | ||||
|         if self.forbid_entities: | ||||
|             parser.EntityDeclHandler = self.defused_entity_decl | ||||
|             parser.UnparsedEntityDeclHandler = self.defused_unparsed_entity_decl | ||||
|         if self.forbid_external: | ||||
|             parser.ExternalEntityRefHandler = self.defused_external_entity_ref_handler | ||||
| 
 | ||||
|     def defused_start_doctype_decl(self, name, sysid, pubid, has_internal_subset): | ||||
|         raise DTDForbidden(name, sysid, pubid) | ||||
| 
 | ||||
|     def defused_entity_decl( | ||||
|         self, name, is_parameter_entity, value, base, sysid, pubid, notation_name | ||||
|     ): | ||||
|         raise EntitiesForbidden(name, value, base, sysid, pubid, notation_name) | ||||
| 
 | ||||
|     def defused_unparsed_entity_decl(self, name, base, sysid, pubid, notation_name): | ||||
|         # expat 1.2 | ||||
|         raise EntitiesForbidden(name, None, base, sysid, pubid, notation_name)  # pragma: no cover | ||||
| 
 | ||||
|     def defused_external_entity_ref_handler(self, context, base, sysid, pubid): | ||||
|         raise ExternalReferenceForbidden(context, base, sysid, pubid) | ||||
| 
 | ||||
| 
 | ||||
| # aliases | ||||
| # XMLParse is a typo, keep it for backwards compatibility | ||||
| XMLTreeBuilder = XMLParse = XMLParser = DefusedXMLParser | ||||
| 
 | ||||
| parse, iterparse, fromstring = _generate_etree_functions( | ||||
|     DefusedXMLParser, _TreeBuilder, _parse, _iterparse | ||||
| ) | ||||
| XML = fromstring | ||||
| 
 | ||||
| 
 | ||||
| __all__ = [ | ||||
|     "ParseError", | ||||
|     "XML", | ||||
|     "XMLParse", | ||||
|     "XMLParser", | ||||
|     "XMLTreeBuilder", | ||||
|     "fromstring", | ||||
|     "iterparse", | ||||
|     "parse", | ||||
|     "tostring", | ||||
| ] | ||||
							
								
								
									
										67
									
								
								resources/lib/defusedxml/__init__.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								resources/lib/defusedxml/__init__.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,67 @@ | |||
| # defusedxml | ||||
| # | ||||
| # Copyright (c) 2013 by Christian Heimes <christian@python.org> | ||||
| # Licensed to PSF under a Contributor Agreement. | ||||
| # See https://www.python.org/psf/license for licensing details. | ||||
| """Defuse XML bomb denial of service vulnerabilities | ||||
| """ | ||||
| from __future__ import print_function, absolute_import | ||||
| 
 | ||||
| import warnings | ||||
| 
 | ||||
| from .common import ( | ||||
|     DefusedXmlException, | ||||
|     DTDForbidden, | ||||
|     EntitiesForbidden, | ||||
|     ExternalReferenceForbidden, | ||||
|     NotSupportedError, | ||||
|     _apply_defusing, | ||||
| ) | ||||
| 
 | ||||
| 
 | ||||
| def defuse_stdlib(): | ||||
|     """Monkey patch and defuse all stdlib packages | ||||
| 
 | ||||
|     :warning: The monkey patch is an EXPERIMETNAL feature. | ||||
|     """ | ||||
|     defused = {} | ||||
| 
 | ||||
|     with warnings.catch_warnings(): | ||||
|         from . import cElementTree | ||||
|     from . import ElementTree | ||||
|     from . import minidom | ||||
|     from . import pulldom | ||||
|     from . import sax | ||||
|     from . import expatbuilder | ||||
|     from . import expatreader | ||||
|     from . import xmlrpc | ||||
| 
 | ||||
|     xmlrpc.monkey_patch() | ||||
|     defused[xmlrpc] = None | ||||
| 
 | ||||
|     defused_mods = [ | ||||
|         cElementTree, | ||||
|         ElementTree, | ||||
|         minidom, | ||||
|         pulldom, | ||||
|         sax, | ||||
|         expatbuilder, | ||||
|         expatreader, | ||||
|     ] | ||||
| 
 | ||||
|     for defused_mod in defused_mods: | ||||
|         stdlib_mod = _apply_defusing(defused_mod) | ||||
|         defused[defused_mod] = stdlib_mod | ||||
| 
 | ||||
|     return defused | ||||
| 
 | ||||
| 
 | ||||
| __version__ = "0.7.1" | ||||
| 
 | ||||
| __all__ = [ | ||||
|     "DefusedXmlException", | ||||
|     "DTDForbidden", | ||||
|     "EntitiesForbidden", | ||||
|     "ExternalReferenceForbidden", | ||||
|     "NotSupportedError", | ||||
| ] | ||||
							
								
								
									
										62
									
								
								resources/lib/defusedxml/cElementTree.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								resources/lib/defusedxml/cElementTree.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,62 @@ | |||
| # defusedxml | ||||
| # | ||||
| # Copyright (c) 2013 by Christian Heimes <christian@python.org> | ||||
| # Licensed to PSF under a Contributor Agreement. | ||||
| # See https://www.python.org/psf/license for licensing details. | ||||
| """Defused xml.etree.cElementTree | ||||
| """ | ||||
| from __future__ import absolute_import | ||||
| 
 | ||||
| import warnings | ||||
| 
 | ||||
| from .common import _generate_etree_functions | ||||
| 
 | ||||
| from xml.etree.cElementTree import TreeBuilder as _TreeBuilder | ||||
| from xml.etree.cElementTree import parse as _parse | ||||
| from xml.etree.cElementTree import tostring | ||||
| 
 | ||||
| # iterparse from ElementTree! | ||||
| from xml.etree.ElementTree import iterparse as _iterparse | ||||
| 
 | ||||
| # This module is an alias for ElementTree just like xml.etree.cElementTree | ||||
| from .ElementTree import ( | ||||
|     XML, | ||||
|     XMLParse, | ||||
|     XMLParser, | ||||
|     XMLTreeBuilder, | ||||
|     fromstring, | ||||
|     iterparse, | ||||
|     parse, | ||||
|     tostring, | ||||
|     DefusedXMLParser, | ||||
|     ParseError, | ||||
| ) | ||||
| 
 | ||||
| __origin__ = "xml.etree.cElementTree" | ||||
| 
 | ||||
| 
 | ||||
| warnings.warn( | ||||
|     "defusedxml.cElementTree is deprecated, import from defusedxml.ElementTree instead.", | ||||
|     category=DeprecationWarning, | ||||
|     stacklevel=2, | ||||
| ) | ||||
| 
 | ||||
| # XMLParse is a typo, keep it for backwards compatibility | ||||
| XMLTreeBuilder = XMLParse = XMLParser = DefusedXMLParser | ||||
| 
 | ||||
| parse, iterparse, fromstring = _generate_etree_functions( | ||||
|     DefusedXMLParser, _TreeBuilder, _parse, _iterparse | ||||
| ) | ||||
| XML = fromstring | ||||
| 
 | ||||
| __all__ = [ | ||||
|     "ParseError", | ||||
|     "XML", | ||||
|     "XMLParse", | ||||
|     "XMLParser", | ||||
|     "XMLTreeBuilder", | ||||
|     "fromstring", | ||||
|     "iterparse", | ||||
|     "parse", | ||||
|     "tostring", | ||||
| ] | ||||
							
								
								
									
										129
									
								
								resources/lib/defusedxml/common.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										129
									
								
								resources/lib/defusedxml/common.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,129 @@ | |||
| # defusedxml | ||||
| # | ||||
| # Copyright (c) 2013 by Christian Heimes <christian@python.org> | ||||
| # Licensed to PSF under a Contributor Agreement. | ||||
| # See https://www.python.org/psf/license for licensing details. | ||||
| """Common constants, exceptions and helpe functions | ||||
| """ | ||||
| import sys | ||||
| import xml.parsers.expat | ||||
| 
 | ||||
| PY3 = sys.version_info[0] == 3 | ||||
| 
 | ||||
| # Fail early when pyexpat is not installed correctly | ||||
| if not hasattr(xml.parsers.expat, "ParserCreate"): | ||||
|     raise ImportError("pyexpat")  # pragma: no cover | ||||
| 
 | ||||
| 
 | ||||
| class DefusedXmlException(ValueError): | ||||
|     """Base exception""" | ||||
| 
 | ||||
|     def __repr__(self): | ||||
|         return str(self) | ||||
| 
 | ||||
| 
 | ||||
| class DTDForbidden(DefusedXmlException): | ||||
|     """Document type definition is forbidden""" | ||||
| 
 | ||||
|     def __init__(self, name, sysid, pubid): | ||||
|         super(DTDForbidden, self).__init__() | ||||
|         self.name = name | ||||
|         self.sysid = sysid | ||||
|         self.pubid = pubid | ||||
| 
 | ||||
|     def __str__(self): | ||||
|         tpl = "DTDForbidden(name='{}', system_id={!r}, public_id={!r})" | ||||
|         return tpl.format(self.name, self.sysid, self.pubid) | ||||
| 
 | ||||
| 
 | ||||
| class EntitiesForbidden(DefusedXmlException): | ||||
|     """Entity definition is forbidden""" | ||||
| 
 | ||||
|     def __init__(self, name, value, base, sysid, pubid, notation_name): | ||||
|         super(EntitiesForbidden, self).__init__() | ||||
|         self.name = name | ||||
|         self.value = value | ||||
|         self.base = base | ||||
|         self.sysid = sysid | ||||
|         self.pubid = pubid | ||||
|         self.notation_name = notation_name | ||||
| 
 | ||||
|     def __str__(self): | ||||
|         tpl = "EntitiesForbidden(name='{}', system_id={!r}, public_id={!r})" | ||||
|         return tpl.format(self.name, self.sysid, self.pubid) | ||||
| 
 | ||||
| 
 | ||||
| class ExternalReferenceForbidden(DefusedXmlException): | ||||
|     """Resolving an external reference is forbidden""" | ||||
| 
 | ||||
|     def __init__(self, context, base, sysid, pubid): | ||||
|         super(ExternalReferenceForbidden, self).__init__() | ||||
|         self.context = context | ||||
|         self.base = base | ||||
|         self.sysid = sysid | ||||
|         self.pubid = pubid | ||||
| 
 | ||||
|     def __str__(self): | ||||
|         tpl = "ExternalReferenceForbidden(system_id='{}', public_id={})" | ||||
|         return tpl.format(self.sysid, self.pubid) | ||||
| 
 | ||||
| 
 | ||||
| class NotSupportedError(DefusedXmlException): | ||||
|     """The operation is not supported""" | ||||
| 
 | ||||
| 
 | ||||
| def _apply_defusing(defused_mod): | ||||
|     assert defused_mod is sys.modules[defused_mod.__name__] | ||||
|     stdlib_name = defused_mod.__origin__ | ||||
|     __import__(stdlib_name, {}, {}, ["*"]) | ||||
|     stdlib_mod = sys.modules[stdlib_name] | ||||
|     stdlib_names = set(dir(stdlib_mod)) | ||||
|     for name, obj in vars(defused_mod).items(): | ||||
|         if name.startswith("_") or name not in stdlib_names: | ||||
|             continue | ||||
|         setattr(stdlib_mod, name, obj) | ||||
|     return stdlib_mod | ||||
| 
 | ||||
| 
 | ||||
| def _generate_etree_functions(DefusedXMLParser, _TreeBuilder, _parse, _iterparse): | ||||
|     """Factory for functions needed by etree, dependent on whether | ||||
|     cElementTree or ElementTree is used.""" | ||||
| 
 | ||||
|     def parse(source, parser=None, forbid_dtd=False, forbid_entities=True, forbid_external=True): | ||||
|         if parser is None: | ||||
|             parser = DefusedXMLParser( | ||||
|                 target=_TreeBuilder(), | ||||
|                 forbid_dtd=forbid_dtd, | ||||
|                 forbid_entities=forbid_entities, | ||||
|                 forbid_external=forbid_external, | ||||
|             ) | ||||
|         return _parse(source, parser) | ||||
| 
 | ||||
|     def iterparse( | ||||
|         source, | ||||
|         events=None, | ||||
|         parser=None, | ||||
|         forbid_dtd=False, | ||||
|         forbid_entities=True, | ||||
|         forbid_external=True, | ||||
|     ): | ||||
|         if parser is None: | ||||
|             parser = DefusedXMLParser( | ||||
|                 target=_TreeBuilder(), | ||||
|                 forbid_dtd=forbid_dtd, | ||||
|                 forbid_entities=forbid_entities, | ||||
|                 forbid_external=forbid_external, | ||||
|             ) | ||||
|         return _iterparse(source, events, parser) | ||||
| 
 | ||||
|     def fromstring(text, forbid_dtd=False, forbid_entities=True, forbid_external=True): | ||||
|         parser = DefusedXMLParser( | ||||
|             target=_TreeBuilder(), | ||||
|             forbid_dtd=forbid_dtd, | ||||
|             forbid_entities=forbid_entities, | ||||
|             forbid_external=forbid_external, | ||||
|         ) | ||||
|         parser.feed(text) | ||||
|         return parser.close() | ||||
| 
 | ||||
|     return parse, iterparse, fromstring | ||||
							
								
								
									
										107
									
								
								resources/lib/defusedxml/expatbuilder.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										107
									
								
								resources/lib/defusedxml/expatbuilder.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,107 @@ | |||
| # defusedxml | ||||
| # | ||||
| # Copyright (c) 2013 by Christian Heimes <christian@python.org> | ||||
| # Licensed to PSF under a Contributor Agreement. | ||||
| # See https://www.python.org/psf/license for licensing details. | ||||
| """Defused xml.dom.expatbuilder | ||||
| """ | ||||
| from __future__ import print_function, absolute_import | ||||
| 
 | ||||
| from xml.dom.expatbuilder import ExpatBuilder as _ExpatBuilder | ||||
| from xml.dom.expatbuilder import Namespaces as _Namespaces | ||||
| 
 | ||||
| from .common import DTDForbidden, EntitiesForbidden, ExternalReferenceForbidden | ||||
| 
 | ||||
| __origin__ = "xml.dom.expatbuilder" | ||||
| 
 | ||||
| 
 | ||||
| class DefusedExpatBuilder(_ExpatBuilder): | ||||
|     """Defused document builder""" | ||||
| 
 | ||||
|     def __init__( | ||||
|         self, options=None, forbid_dtd=False, forbid_entities=True, forbid_external=True | ||||
|     ): | ||||
|         _ExpatBuilder.__init__(self, options) | ||||
|         self.forbid_dtd = forbid_dtd | ||||
|         self.forbid_entities = forbid_entities | ||||
|         self.forbid_external = forbid_external | ||||
| 
 | ||||
|     def defused_start_doctype_decl(self, name, sysid, pubid, has_internal_subset): | ||||
|         raise DTDForbidden(name, sysid, pubid) | ||||
| 
 | ||||
|     def defused_entity_decl( | ||||
|         self, name, is_parameter_entity, value, base, sysid, pubid, notation_name | ||||
|     ): | ||||
|         raise EntitiesForbidden(name, value, base, sysid, pubid, notation_name) | ||||
| 
 | ||||
|     def defused_unparsed_entity_decl(self, name, base, sysid, pubid, notation_name): | ||||
|         # expat 1.2 | ||||
|         raise EntitiesForbidden(name, None, base, sysid, pubid, notation_name)  # pragma: no cover | ||||
| 
 | ||||
|     def defused_external_entity_ref_handler(self, context, base, sysid, pubid): | ||||
|         raise ExternalReferenceForbidden(context, base, sysid, pubid) | ||||
| 
 | ||||
|     def install(self, parser): | ||||
|         _ExpatBuilder.install(self, parser) | ||||
| 
 | ||||
|         if self.forbid_dtd: | ||||
|             parser.StartDoctypeDeclHandler = self.defused_start_doctype_decl | ||||
|         if self.forbid_entities: | ||||
|             # if self._options.entities: | ||||
|             parser.EntityDeclHandler = self.defused_entity_decl | ||||
|             parser.UnparsedEntityDeclHandler = self.defused_unparsed_entity_decl | ||||
|         if self.forbid_external: | ||||
|             parser.ExternalEntityRefHandler = self.defused_external_entity_ref_handler | ||||
| 
 | ||||
| 
 | ||||
| class DefusedExpatBuilderNS(_Namespaces, DefusedExpatBuilder): | ||||
|     """Defused document builder that supports namespaces.""" | ||||
| 
 | ||||
|     def install(self, parser): | ||||
|         DefusedExpatBuilder.install(self, parser) | ||||
|         if self._options.namespace_declarations: | ||||
|             parser.StartNamespaceDeclHandler = self.start_namespace_decl_handler | ||||
| 
 | ||||
|     def reset(self): | ||||
|         DefusedExpatBuilder.reset(self) | ||||
|         self._initNamespaces() | ||||
| 
 | ||||
| 
 | ||||
| def parse(file, namespaces=True, forbid_dtd=False, forbid_entities=True, forbid_external=True): | ||||
|     """Parse a document, returning the resulting Document node. | ||||
| 
 | ||||
|     'file' may be either a file name or an open file object. | ||||
|     """ | ||||
|     if namespaces: | ||||
|         build_builder = DefusedExpatBuilderNS | ||||
|     else: | ||||
|         build_builder = DefusedExpatBuilder | ||||
|     builder = build_builder( | ||||
|         forbid_dtd=forbid_dtd, forbid_entities=forbid_entities, forbid_external=forbid_external | ||||
|     ) | ||||
| 
 | ||||
|     if isinstance(file, str): | ||||
|         fp = open(file, "rb") | ||||
|         try: | ||||
|             result = builder.parseFile(fp) | ||||
|         finally: | ||||
|             fp.close() | ||||
|     else: | ||||
|         result = builder.parseFile(file) | ||||
|     return result | ||||
| 
 | ||||
| 
 | ||||
| def parseString( | ||||
|     string, namespaces=True, forbid_dtd=False, forbid_entities=True, forbid_external=True | ||||
| ): | ||||
|     """Parse a document from a string, returning the resulting | ||||
|     Document node. | ||||
|     """ | ||||
|     if namespaces: | ||||
|         build_builder = DefusedExpatBuilderNS | ||||
|     else: | ||||
|         build_builder = DefusedExpatBuilder | ||||
|     builder = build_builder( | ||||
|         forbid_dtd=forbid_dtd, forbid_entities=forbid_entities, forbid_external=forbid_external | ||||
|     ) | ||||
|     return builder.parseString(string) | ||||
							
								
								
									
										61
									
								
								resources/lib/defusedxml/expatreader.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								resources/lib/defusedxml/expatreader.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,61 @@ | |||
| # defusedxml | ||||
| # | ||||
| # Copyright (c) 2013 by Christian Heimes <christian@python.org> | ||||
| # Licensed to PSF under a Contributor Agreement. | ||||
| # See https://www.python.org/psf/license for licensing details. | ||||
| """Defused xml.sax.expatreader | ||||
| """ | ||||
| from __future__ import print_function, absolute_import | ||||
| 
 | ||||
| from xml.sax.expatreader import ExpatParser as _ExpatParser | ||||
| 
 | ||||
| from .common import DTDForbidden, EntitiesForbidden, ExternalReferenceForbidden | ||||
| 
 | ||||
| __origin__ = "xml.sax.expatreader" | ||||
| 
 | ||||
| 
 | ||||
| class DefusedExpatParser(_ExpatParser): | ||||
|     """Defused SAX driver for the pyexpat C module.""" | ||||
| 
 | ||||
|     def __init__( | ||||
|         self, | ||||
|         namespaceHandling=0, | ||||
|         bufsize=2 ** 16 - 20, | ||||
|         forbid_dtd=False, | ||||
|         forbid_entities=True, | ||||
|         forbid_external=True, | ||||
|     ): | ||||
|         _ExpatParser.__init__(self, namespaceHandling, bufsize) | ||||
|         self.forbid_dtd = forbid_dtd | ||||
|         self.forbid_entities = forbid_entities | ||||
|         self.forbid_external = forbid_external | ||||
| 
 | ||||
|     def defused_start_doctype_decl(self, name, sysid, pubid, has_internal_subset): | ||||
|         raise DTDForbidden(name, sysid, pubid) | ||||
| 
 | ||||
|     def defused_entity_decl( | ||||
|         self, name, is_parameter_entity, value, base, sysid, pubid, notation_name | ||||
|     ): | ||||
|         raise EntitiesForbidden(name, value, base, sysid, pubid, notation_name) | ||||
| 
 | ||||
|     def defused_unparsed_entity_decl(self, name, base, sysid, pubid, notation_name): | ||||
|         # expat 1.2 | ||||
|         raise EntitiesForbidden(name, None, base, sysid, pubid, notation_name)  # pragma: no cover | ||||
| 
 | ||||
|     def defused_external_entity_ref_handler(self, context, base, sysid, pubid): | ||||
|         raise ExternalReferenceForbidden(context, base, sysid, pubid) | ||||
| 
 | ||||
|     def reset(self): | ||||
|         _ExpatParser.reset(self) | ||||
|         parser = self._parser | ||||
|         if self.forbid_dtd: | ||||
|             parser.StartDoctypeDeclHandler = self.defused_start_doctype_decl | ||||
|         if self.forbid_entities: | ||||
|             parser.EntityDeclHandler = self.defused_entity_decl | ||||
|             parser.UnparsedEntityDeclHandler = self.defused_unparsed_entity_decl | ||||
|         if self.forbid_external: | ||||
|             parser.ExternalEntityRefHandler = self.defused_external_entity_ref_handler | ||||
| 
 | ||||
| 
 | ||||
| def create_parser(*args, **kwargs): | ||||
|     return DefusedExpatParser(*args, **kwargs) | ||||
							
								
								
									
										153
									
								
								resources/lib/defusedxml/lxml.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										153
									
								
								resources/lib/defusedxml/lxml.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,153 @@ | |||
| # defusedxml | ||||
| # | ||||
| # Copyright (c) 2013 by Christian Heimes <christian@python.org> | ||||
| # Licensed to PSF under a Contributor Agreement. | ||||
| # See https://www.python.org/psf/license for licensing details. | ||||
| """DEPRECATED Example code for lxml.etree protection | ||||
| 
 | ||||
| The code has NO protection against decompression bombs. | ||||
| """ | ||||
| from __future__ import print_function, absolute_import | ||||
| 
 | ||||
| import threading | ||||
| import warnings | ||||
| 
 | ||||
| from lxml import etree as _etree | ||||
| 
 | ||||
| from .common import DTDForbidden, EntitiesForbidden, NotSupportedError | ||||
| 
 | ||||
| LXML3 = _etree.LXML_VERSION[0] >= 3 | ||||
| 
 | ||||
| __origin__ = "lxml.etree" | ||||
| 
 | ||||
| tostring = _etree.tostring | ||||
| 
 | ||||
| 
 | ||||
| warnings.warn( | ||||
|     "defusedxml.lxml is no longer supported and will be removed in a future release.", | ||||
|     category=DeprecationWarning, | ||||
|     stacklevel=2, | ||||
| ) | ||||
| 
 | ||||
| 
 | ||||
| class RestrictedElement(_etree.ElementBase): | ||||
|     """A restricted Element class that filters out instances of some classes""" | ||||
| 
 | ||||
|     __slots__ = () | ||||
|     # blacklist = (etree._Entity, etree._ProcessingInstruction, etree._Comment) | ||||
|     blacklist = _etree._Entity | ||||
| 
 | ||||
|     def _filter(self, iterator): | ||||
|         blacklist = self.blacklist | ||||
|         for child in iterator: | ||||
|             if isinstance(child, blacklist): | ||||
|                 continue | ||||
|             yield child | ||||
| 
 | ||||
|     def __iter__(self): | ||||
|         iterator = super(RestrictedElement, self).__iter__() | ||||
|         return self._filter(iterator) | ||||
| 
 | ||||
|     def iterchildren(self, tag=None, reversed=False): | ||||
|         iterator = super(RestrictedElement, self).iterchildren(tag=tag, reversed=reversed) | ||||
|         return self._filter(iterator) | ||||
| 
 | ||||
|     def iter(self, tag=None, *tags): | ||||
|         iterator = super(RestrictedElement, self).iter(tag=tag, *tags) | ||||
|         return self._filter(iterator) | ||||
| 
 | ||||
|     def iterdescendants(self, tag=None, *tags): | ||||
|         iterator = super(RestrictedElement, self).iterdescendants(tag=tag, *tags) | ||||
|         return self._filter(iterator) | ||||
| 
 | ||||
|     def itersiblings(self, tag=None, preceding=False): | ||||
|         iterator = super(RestrictedElement, self).itersiblings(tag=tag, preceding=preceding) | ||||
|         return self._filter(iterator) | ||||
| 
 | ||||
|     def getchildren(self): | ||||
|         iterator = super(RestrictedElement, self).__iter__() | ||||
|         return list(self._filter(iterator)) | ||||
| 
 | ||||
|     def getiterator(self, tag=None): | ||||
|         iterator = super(RestrictedElement, self).getiterator(tag) | ||||
|         return self._filter(iterator) | ||||
| 
 | ||||
| 
 | ||||
| class GlobalParserTLS(threading.local): | ||||
|     """Thread local context for custom parser instances""" | ||||
| 
 | ||||
|     parser_config = { | ||||
|         "resolve_entities": False, | ||||
|         # 'remove_comments': True, | ||||
|         # 'remove_pis': True, | ||||
|     } | ||||
| 
 | ||||
|     element_class = RestrictedElement | ||||
| 
 | ||||
|     def createDefaultParser(self): | ||||
|         parser = _etree.XMLParser(**self.parser_config) | ||||
|         element_class = self.element_class | ||||
|         if self.element_class is not None: | ||||
|             lookup = _etree.ElementDefaultClassLookup(element=element_class) | ||||
|             parser.set_element_class_lookup(lookup) | ||||
|         return parser | ||||
| 
 | ||||
|     def setDefaultParser(self, parser): | ||||
|         self._default_parser = parser | ||||
| 
 | ||||
|     def getDefaultParser(self): | ||||
|         parser = getattr(self, "_default_parser", None) | ||||
|         if parser is None: | ||||
|             parser = self.createDefaultParser() | ||||
|             self.setDefaultParser(parser) | ||||
|         return parser | ||||
| 
 | ||||
| 
 | ||||
| _parser_tls = GlobalParserTLS() | ||||
| getDefaultParser = _parser_tls.getDefaultParser | ||||
| 
 | ||||
| 
 | ||||
| def check_docinfo(elementtree, forbid_dtd=False, forbid_entities=True): | ||||
|     """Check docinfo of an element tree for DTD and entity declarations | ||||
| 
 | ||||
|     The check for entity declarations needs lxml 3 or newer. lxml 2.x does | ||||
|     not support dtd.iterentities(). | ||||
|     """ | ||||
|     docinfo = elementtree.docinfo | ||||
|     if docinfo.doctype: | ||||
|         if forbid_dtd: | ||||
|             raise DTDForbidden(docinfo.doctype, docinfo.system_url, docinfo.public_id) | ||||
|         if forbid_entities and not LXML3: | ||||
|             # lxml < 3 has no iterentities() | ||||
|             raise NotSupportedError("Unable to check for entity declarations " "in lxml 2.x") | ||||
| 
 | ||||
|     if forbid_entities: | ||||
|         for dtd in docinfo.internalDTD, docinfo.externalDTD: | ||||
|             if dtd is None: | ||||
|                 continue | ||||
|             for entity in dtd.iterentities(): | ||||
|                 raise EntitiesForbidden(entity.name, entity.content, None, None, None, None) | ||||
| 
 | ||||
| 
 | ||||
| def parse(source, parser=None, base_url=None, forbid_dtd=False, forbid_entities=True): | ||||
|     if parser is None: | ||||
|         parser = getDefaultParser() | ||||
|     elementtree = _etree.parse(source, parser, base_url=base_url) | ||||
|     check_docinfo(elementtree, forbid_dtd, forbid_entities) | ||||
|     return elementtree | ||||
| 
 | ||||
| 
 | ||||
| def fromstring(text, parser=None, base_url=None, forbid_dtd=False, forbid_entities=True): | ||||
|     if parser is None: | ||||
|         parser = getDefaultParser() | ||||
|     rootelement = _etree.fromstring(text, parser, base_url=base_url) | ||||
|     elementtree = rootelement.getroottree() | ||||
|     check_docinfo(elementtree, forbid_dtd, forbid_entities) | ||||
|     return rootelement | ||||
| 
 | ||||
| 
 | ||||
| XML = fromstring | ||||
| 
 | ||||
| 
 | ||||
| def iterparse(*args, **kwargs): | ||||
|     raise NotSupportedError("defused lxml.etree.iterparse not available") | ||||
							
								
								
									
										63
									
								
								resources/lib/defusedxml/minidom.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								resources/lib/defusedxml/minidom.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,63 @@ | |||
| # defusedxml | ||||
| # | ||||
| # Copyright (c) 2013 by Christian Heimes <christian@python.org> | ||||
| # Licensed to PSF under a Contributor Agreement. | ||||
| # See https://www.python.org/psf/license for licensing details. | ||||
| """Defused xml.dom.minidom | ||||
| """ | ||||
| from __future__ import print_function, absolute_import | ||||
| 
 | ||||
| from xml.dom.minidom import _do_pulldom_parse | ||||
| from . import expatbuilder as _expatbuilder | ||||
| from . import pulldom as _pulldom | ||||
| 
 | ||||
| __origin__ = "xml.dom.minidom" | ||||
| 
 | ||||
| 
 | ||||
| def parse( | ||||
|     file, parser=None, bufsize=None, forbid_dtd=False, forbid_entities=True, forbid_external=True | ||||
| ): | ||||
|     """Parse a file into a DOM by filename or file object.""" | ||||
|     if parser is None and not bufsize: | ||||
|         return _expatbuilder.parse( | ||||
|             file, | ||||
|             forbid_dtd=forbid_dtd, | ||||
|             forbid_entities=forbid_entities, | ||||
|             forbid_external=forbid_external, | ||||
|         ) | ||||
|     else: | ||||
|         return _do_pulldom_parse( | ||||
|             _pulldom.parse, | ||||
|             (file,), | ||||
|             { | ||||
|                 "parser": parser, | ||||
|                 "bufsize": bufsize, | ||||
|                 "forbid_dtd": forbid_dtd, | ||||
|                 "forbid_entities": forbid_entities, | ||||
|                 "forbid_external": forbid_external, | ||||
|             }, | ||||
|         ) | ||||
| 
 | ||||
| 
 | ||||
| def parseString( | ||||
|     string, parser=None, forbid_dtd=False, forbid_entities=True, forbid_external=True | ||||
| ): | ||||
|     """Parse a file into a DOM from a string.""" | ||||
|     if parser is None: | ||||
|         return _expatbuilder.parseString( | ||||
|             string, | ||||
|             forbid_dtd=forbid_dtd, | ||||
|             forbid_entities=forbid_entities, | ||||
|             forbid_external=forbid_external, | ||||
|         ) | ||||
|     else: | ||||
|         return _do_pulldom_parse( | ||||
|             _pulldom.parseString, | ||||
|             (string,), | ||||
|             { | ||||
|                 "parser": parser, | ||||
|                 "forbid_dtd": forbid_dtd, | ||||
|                 "forbid_entities": forbid_entities, | ||||
|                 "forbid_external": forbid_external, | ||||
|             }, | ||||
|         ) | ||||
							
								
								
									
										41
									
								
								resources/lib/defusedxml/pulldom.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								resources/lib/defusedxml/pulldom.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,41 @@ | |||
| # defusedxml | ||||
| # | ||||
| # Copyright (c) 2013 by Christian Heimes <christian@python.org> | ||||
| # Licensed to PSF under a Contributor Agreement. | ||||
| # See https://www.python.org/psf/license for licensing details. | ||||
| """Defused xml.dom.pulldom | ||||
| """ | ||||
| from __future__ import print_function, absolute_import | ||||
| 
 | ||||
| from xml.dom.pulldom import parse as _parse | ||||
| from xml.dom.pulldom import parseString as _parseString | ||||
| from .sax import make_parser | ||||
| 
 | ||||
| __origin__ = "xml.dom.pulldom" | ||||
| 
 | ||||
| 
 | ||||
| def parse( | ||||
|     stream_or_string, | ||||
|     parser=None, | ||||
|     bufsize=None, | ||||
|     forbid_dtd=False, | ||||
|     forbid_entities=True, | ||||
|     forbid_external=True, | ||||
| ): | ||||
|     if parser is None: | ||||
|         parser = make_parser() | ||||
|         parser.forbid_dtd = forbid_dtd | ||||
|         parser.forbid_entities = forbid_entities | ||||
|         parser.forbid_external = forbid_external | ||||
|     return _parse(stream_or_string, parser, bufsize) | ||||
| 
 | ||||
| 
 | ||||
| def parseString( | ||||
|     string, parser=None, forbid_dtd=False, forbid_entities=True, forbid_external=True | ||||
| ): | ||||
|     if parser is None: | ||||
|         parser = make_parser() | ||||
|         parser.forbid_dtd = forbid_dtd | ||||
|         parser.forbid_entities = forbid_entities | ||||
|         parser.forbid_external = forbid_external | ||||
|     return _parseString(string, parser) | ||||
							
								
								
									
										60
									
								
								resources/lib/defusedxml/sax.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								resources/lib/defusedxml/sax.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,60 @@ | |||
| # defusedxml | ||||
| # | ||||
| # Copyright (c) 2013 by Christian Heimes <christian@python.org> | ||||
| # Licensed to PSF under a Contributor Agreement. | ||||
| # See https://www.python.org/psf/license for licensing details. | ||||
| """Defused xml.sax | ||||
| """ | ||||
| from __future__ import print_function, absolute_import | ||||
| 
 | ||||
| from xml.sax import InputSource as _InputSource | ||||
| from xml.sax import ErrorHandler as _ErrorHandler | ||||
| 
 | ||||
| from . import expatreader | ||||
| 
 | ||||
| __origin__ = "xml.sax" | ||||
| 
 | ||||
| 
 | ||||
| def parse( | ||||
|     source, | ||||
|     handler, | ||||
|     errorHandler=_ErrorHandler(), | ||||
|     forbid_dtd=False, | ||||
|     forbid_entities=True, | ||||
|     forbid_external=True, | ||||
| ): | ||||
|     parser = make_parser() | ||||
|     parser.setContentHandler(handler) | ||||
|     parser.setErrorHandler(errorHandler) | ||||
|     parser.forbid_dtd = forbid_dtd | ||||
|     parser.forbid_entities = forbid_entities | ||||
|     parser.forbid_external = forbid_external | ||||
|     parser.parse(source) | ||||
| 
 | ||||
| 
 | ||||
| def parseString( | ||||
|     string, | ||||
|     handler, | ||||
|     errorHandler=_ErrorHandler(), | ||||
|     forbid_dtd=False, | ||||
|     forbid_entities=True, | ||||
|     forbid_external=True, | ||||
| ): | ||||
|     from io import BytesIO | ||||
| 
 | ||||
|     if errorHandler is None: | ||||
|         errorHandler = _ErrorHandler() | ||||
|     parser = make_parser() | ||||
|     parser.setContentHandler(handler) | ||||
|     parser.setErrorHandler(errorHandler) | ||||
|     parser.forbid_dtd = forbid_dtd | ||||
|     parser.forbid_entities = forbid_entities | ||||
|     parser.forbid_external = forbid_external | ||||
| 
 | ||||
|     inpsrc = _InputSource() | ||||
|     inpsrc.setByteStream(BytesIO(string)) | ||||
|     parser.parse(inpsrc) | ||||
| 
 | ||||
| 
 | ||||
| def make_parser(parser_list=[]): | ||||
|     return expatreader.create_parser() | ||||
							
								
								
									
										153
									
								
								resources/lib/defusedxml/xmlrpc.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										153
									
								
								resources/lib/defusedxml/xmlrpc.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,153 @@ | |||
| # defusedxml | ||||
| # | ||||
| # Copyright (c) 2013 by Christian Heimes <christian@python.org> | ||||
| # Licensed to PSF under a Contributor Agreement. | ||||
| # See https://www.python.org/psf/license for licensing details. | ||||
| """Defused xmlrpclib | ||||
| 
 | ||||
| Also defuses gzip bomb | ||||
| """ | ||||
| from __future__ import print_function, absolute_import | ||||
| 
 | ||||
| import io | ||||
| 
 | ||||
| from .common import DTDForbidden, EntitiesForbidden, ExternalReferenceForbidden, PY3 | ||||
| 
 | ||||
| if PY3: | ||||
|     __origin__ = "xmlrpc.client" | ||||
|     from xmlrpc.client import ExpatParser | ||||
|     from xmlrpc import client as xmlrpc_client | ||||
|     from xmlrpc import server as xmlrpc_server | ||||
|     from xmlrpc.client import gzip_decode as _orig_gzip_decode | ||||
|     from xmlrpc.client import GzipDecodedResponse as _OrigGzipDecodedResponse | ||||
| else: | ||||
|     __origin__ = "xmlrpclib" | ||||
|     from xmlrpclib import ExpatParser | ||||
|     import xmlrpclib as xmlrpc_client | ||||
| 
 | ||||
|     xmlrpc_server = None | ||||
|     from xmlrpclib import gzip_decode as _orig_gzip_decode | ||||
|     from xmlrpclib import GzipDecodedResponse as _OrigGzipDecodedResponse | ||||
| 
 | ||||
| try: | ||||
|     import gzip | ||||
| except ImportError:  # pragma: no cover | ||||
|     gzip = None | ||||
| 
 | ||||
| 
 | ||||
| # Limit maximum request size to prevent resource exhaustion DoS | ||||
| # Also used to limit maximum amount of gzip decoded data in order to prevent | ||||
| # decompression bombs | ||||
| # A value of -1 or smaller disables the limit | ||||
| MAX_DATA = 30 * 1024 * 1024  # 30 MB | ||||
| 
 | ||||
| 
 | ||||
| def defused_gzip_decode(data, limit=None): | ||||
|     """gzip encoded data -> unencoded data | ||||
| 
 | ||||
|     Decode data using the gzip content encoding as described in RFC 1952 | ||||
|     """ | ||||
|     if not gzip:  # pragma: no cover | ||||
|         raise NotImplementedError | ||||
|     if limit is None: | ||||
|         limit = MAX_DATA | ||||
|     f = io.BytesIO(data) | ||||
|     gzf = gzip.GzipFile(mode="rb", fileobj=f) | ||||
|     try: | ||||
|         if limit < 0:  # no limit | ||||
|             decoded = gzf.read() | ||||
|         else: | ||||
|             decoded = gzf.read(limit + 1) | ||||
|     except IOError:  # pragma: no cover | ||||
|         raise ValueError("invalid data") | ||||
|     f.close() | ||||
|     gzf.close() | ||||
|     if limit >= 0 and len(decoded) > limit: | ||||
|         raise ValueError("max gzipped payload length exceeded") | ||||
|     return decoded | ||||
| 
 | ||||
| 
 | ||||
| class DefusedGzipDecodedResponse(gzip.GzipFile if gzip else object): | ||||
|     """a file-like object to decode a response encoded with the gzip | ||||
|     method, as described in RFC 1952. | ||||
|     """ | ||||
| 
 | ||||
|     def __init__(self, response, limit=None): | ||||
|         # response doesn't support tell() and read(), required by | ||||
|         # GzipFile | ||||
|         if not gzip:  # pragma: no cover | ||||
|             raise NotImplementedError | ||||
|         self.limit = limit = limit if limit is not None else MAX_DATA | ||||
|         if limit < 0:  # no limit | ||||
|             data = response.read() | ||||
|             self.readlength = None | ||||
|         else: | ||||
|             data = response.read(limit + 1) | ||||
|             self.readlength = 0 | ||||
|         if limit >= 0 and len(data) > limit: | ||||
|             raise ValueError("max payload length exceeded") | ||||
|         self.stringio = io.BytesIO(data) | ||||
|         gzip.GzipFile.__init__(self, mode="rb", fileobj=self.stringio) | ||||
| 
 | ||||
|     def read(self, n): | ||||
|         if self.limit >= 0: | ||||
|             left = self.limit - self.readlength | ||||
|             n = min(n, left + 1) | ||||
|             data = gzip.GzipFile.read(self, n) | ||||
|             self.readlength += len(data) | ||||
|             if self.readlength > self.limit: | ||||
|                 raise ValueError("max payload length exceeded") | ||||
|             return data | ||||
|         else: | ||||
|             return gzip.GzipFile.read(self, n) | ||||
| 
 | ||||
|     def close(self): | ||||
|         gzip.GzipFile.close(self) | ||||
|         self.stringio.close() | ||||
| 
 | ||||
| 
 | ||||
| class DefusedExpatParser(ExpatParser): | ||||
|     def __init__(self, target, forbid_dtd=False, forbid_entities=True, forbid_external=True): | ||||
|         ExpatParser.__init__(self, target) | ||||
|         self.forbid_dtd = forbid_dtd | ||||
|         self.forbid_entities = forbid_entities | ||||
|         self.forbid_external = forbid_external | ||||
|         parser = self._parser | ||||
|         if self.forbid_dtd: | ||||
|             parser.StartDoctypeDeclHandler = self.defused_start_doctype_decl | ||||
|         if self.forbid_entities: | ||||
|             parser.EntityDeclHandler = self.defused_entity_decl | ||||
|             parser.UnparsedEntityDeclHandler = self.defused_unparsed_entity_decl | ||||
|         if self.forbid_external: | ||||
|             parser.ExternalEntityRefHandler = self.defused_external_entity_ref_handler | ||||
| 
 | ||||
|     def defused_start_doctype_decl(self, name, sysid, pubid, has_internal_subset): | ||||
|         raise DTDForbidden(name, sysid, pubid) | ||||
| 
 | ||||
|     def defused_entity_decl( | ||||
|         self, name, is_parameter_entity, value, base, sysid, pubid, notation_name | ||||
|     ): | ||||
|         raise EntitiesForbidden(name, value, base, sysid, pubid, notation_name) | ||||
| 
 | ||||
|     def defused_unparsed_entity_decl(self, name, base, sysid, pubid, notation_name): | ||||
|         # expat 1.2 | ||||
|         raise EntitiesForbidden(name, None, base, sysid, pubid, notation_name)  # pragma: no cover | ||||
| 
 | ||||
|     def defused_external_entity_ref_handler(self, context, base, sysid, pubid): | ||||
|         raise ExternalReferenceForbidden(context, base, sysid, pubid) | ||||
| 
 | ||||
| 
 | ||||
| def monkey_patch(): | ||||
|     xmlrpc_client.FastParser = DefusedExpatParser | ||||
|     xmlrpc_client.GzipDecodedResponse = DefusedGzipDecodedResponse | ||||
|     xmlrpc_client.gzip_decode = defused_gzip_decode | ||||
|     if xmlrpc_server: | ||||
|         xmlrpc_server.gzip_decode = defused_gzip_decode | ||||
| 
 | ||||
| 
 | ||||
| def unmonkey_patch(): | ||||
|     xmlrpc_client.FastParser = None | ||||
|     xmlrpc_client.GzipDecodedResponse = _OrigGzipDecodedResponse | ||||
|     xmlrpc_client.gzip_decode = _orig_gzip_decode | ||||
|     if xmlrpc_server: | ||||
|         xmlrpc_server.gzip_decode = _orig_gzip_decode | ||||
							
								
								
									
										4
									
								
								resources/lib/deps/__init__.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								resources/lib/deps/__init__.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,4 @@ | |||
| import os | ||||
| import sys | ||||
| 
 | ||||
| sys.path.insert(1, os.path.join(os.path.dirname(__file__))) | ||||
							
								
								
									
										4417
									
								
								resources/lib/deps/bottle.py
									
										
									
									
									
										Executable file
									
								
							
							
						
						
									
										4417
									
								
								resources/lib/deps/bottle.py
									
										
									
									
									
										Executable file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										307
									
								
								resources/lib/deps/simplecache.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										307
									
								
								resources/lib/deps/simplecache.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,307 @@ | |||
| #!/usr/bin/python | ||||
| # -*- coding: utf-8 -*- | ||||
| 
 | ||||
| '''provides a simple stateless caching system for Kodi addons and plugins''' | ||||
| 
 | ||||
| import sys | ||||
| import xbmcvfs | ||||
| import xbmcgui | ||||
| import xbmc | ||||
| import xbmcaddon | ||||
| import datetime | ||||
| import time | ||||
| import sqlite3 | ||||
| import json | ||||
| from functools import reduce | ||||
| 
 | ||||
| class SimpleCache(object): | ||||
|     '''simple stateless caching system for Kodi''' | ||||
|     enable_mem_cache = True | ||||
|     data_is_json = False | ||||
|     global_checksum = None | ||||
|     _exit = False | ||||
|     _auto_clean_interval = datetime.timedelta(hours=4) | ||||
|     _win = None | ||||
|     _busy_tasks = [] | ||||
|     _database = None | ||||
| 
 | ||||
|     def __init__(self, addon_id): | ||||
|         '''Initialize our caching class''' | ||||
|         self.addon_id = addon_id | ||||
|         self._win = xbmcgui.Window(10000) | ||||
|         self._monitor = xbmc.Monitor() | ||||
|         self.check_cleanup() | ||||
|         self._log_msg("Initialized") | ||||
| 
 | ||||
|     def close(self): | ||||
|         '''tell any tasks to stop immediately (as we can be called multithreaded) and cleanup objects''' | ||||
|         self._exit = True | ||||
|         # wait for all tasks to complete | ||||
|         while self._busy_tasks and not self._monitor.abortRequested(): | ||||
|             xbmc.sleep(25) | ||||
|         del self._win | ||||
|         del self._monitor | ||||
|         self._log_msg("Closed") | ||||
| 
 | ||||
|     def __del__(self): | ||||
|         '''make sure close is called''' | ||||
|         if not self._exit: | ||||
|             self.close() | ||||
| 
 | ||||
|     def get(self, endpoint, checksum="", json_data=False): | ||||
|         ''' | ||||
|             get object from cache and return the results | ||||
|             endpoint: the (unique) name of the cache object as reference | ||||
|             checkum: optional argument to check if the checksum in the cacheobject matches the checkum provided | ||||
|         ''' | ||||
|         checksum = self._get_checksum(checksum) | ||||
|         cur_time = self._get_timestamp(datetime.datetime.now()) | ||||
|         result = None | ||||
|         # 1: try memory cache first | ||||
|         if self.enable_mem_cache: | ||||
|             result = self._get_mem_cache(endpoint, checksum, cur_time, json_data) | ||||
| 
 | ||||
|         # 2: fallback to _database cache | ||||
|         if result is None: | ||||
|             result = self._get_db_cache(endpoint, checksum, cur_time, json_data) | ||||
| 
 | ||||
|         return result | ||||
| 
 | ||||
|     def set(self, endpoint, data, checksum="", expiration=datetime.timedelta(days=30), json_data=False): | ||||
|         ''' | ||||
|             set data in cache | ||||
|         ''' | ||||
|         task_name = "set.%s" % endpoint | ||||
|         self._busy_tasks.append(task_name) | ||||
|         checksum = self._get_checksum(checksum) | ||||
|         expires = self._get_timestamp(datetime.datetime.now() + expiration) | ||||
| 
 | ||||
|         # memory cache: write to window property | ||||
|         if self.enable_mem_cache and not self._exit: | ||||
|             self._set_mem_cache(endpoint, checksum, expires, data, json_data) | ||||
| 
 | ||||
|         # db cache | ||||
|         if not self._exit: | ||||
|             self._set_db_cache(endpoint, checksum, expires, data, json_data) | ||||
| 
 | ||||
|         # remove this task from list | ||||
|         self._busy_tasks.remove(task_name) | ||||
| 
 | ||||
|     def check_cleanup(self): | ||||
|         '''check if cleanup is needed - public method, may be called by calling addon''' | ||||
|         cur_time = datetime.datetime.now() | ||||
|         lastexecuted = self._win.getProperty("simplecache.clean.lastexecuted") | ||||
|         if not lastexecuted: | ||||
|             self._win.setProperty("simplecache.clean.lastexecuted", repr(cur_time)) | ||||
|         elif (eval(lastexecuted) + self._auto_clean_interval) < cur_time: | ||||
|             # cleanup needed... | ||||
|             self._do_cleanup() | ||||
| 
 | ||||
|     def _get_mem_cache(self, endpoint, checksum, cur_time, json_data): | ||||
|         ''' | ||||
|             get cache data from memory cache | ||||
|             we use window properties because we need to be stateless | ||||
|         ''' | ||||
|         result = None | ||||
|         cachedata = self._win.getProperty(endpoint) | ||||
| 
 | ||||
|         if cachedata: | ||||
|             if json_data or self.data_is_json: | ||||
|                 cachedata = json.loads(cachedata) | ||||
|             else: | ||||
|                 cachedata = eval(cachedata) | ||||
|             if cachedata[0] > cur_time: | ||||
|                 if not checksum or checksum == cachedata[2]: | ||||
|                     result = cachedata[1] | ||||
|         return result | ||||
| 
 | ||||
|     def _set_mem_cache(self, endpoint, checksum, expires, data, json_data): | ||||
|         ''' | ||||
|             window property cache as alternative for memory cache | ||||
|             usefull for (stateless) plugins | ||||
|         ''' | ||||
|         cachedata = (expires, data, checksum) | ||||
|         if json_data or self.data_is_json: | ||||
|             cachedata_str = json.dumps(cachedata) | ||||
|         else: | ||||
|             cachedata_str = repr(cachedata) | ||||
|         self._win.setProperty(endpoint, cachedata_str) | ||||
| 
 | ||||
| 
 | ||||
|     def _get_db_cache(self, endpoint, checksum, cur_time, json_data): | ||||
|         '''get cache data from sqllite _database''' | ||||
|         result = None | ||||
|         query = "SELECT expires, data, checksum FROM simplecache WHERE id = ?" | ||||
|         cache_data = self._execute_sql(query, (endpoint,)) | ||||
|         if cache_data: | ||||
|             cache_data = cache_data.fetchone() | ||||
|             if cache_data and cache_data[0] > cur_time: | ||||
|                 if not checksum or cache_data[2] == checksum: | ||||
|                     if json_data or self.data_is_json: | ||||
|                         result = json.loads(cache_data[1]) | ||||
|                     else: | ||||
|                         result = eval(cache_data[1]) | ||||
|                     # also set result in memory cache for further access | ||||
|                     if self.enable_mem_cache: | ||||
|                         self._set_mem_cache(endpoint, checksum, cache_data[0], result, json_data) | ||||
|         return result | ||||
| 
 | ||||
|     def _set_db_cache(self, endpoint, checksum, expires, data, json_data): | ||||
|         ''' store cache data in _database ''' | ||||
|         query = "INSERT OR REPLACE INTO simplecache( id, expires, data, checksum) VALUES (?, ?, ?, ?)" | ||||
|         if json_data or self.data_is_json: | ||||
|             data = json.dumps(data) | ||||
|         else: | ||||
|             data = repr(data) | ||||
|         self._execute_sql(query, (endpoint, expires, data, checksum)) | ||||
| 
 | ||||
|     def _do_cleanup(self): | ||||
|         '''perform cleanup task''' | ||||
|         if self._exit or self._monitor.abortRequested(): | ||||
|             return | ||||
|         self._busy_tasks.append(__name__) | ||||
|         cur_time = datetime.datetime.now() | ||||
|         cur_timestamp = self._get_timestamp(cur_time) | ||||
|         self._log_msg("Running cleanup...") | ||||
|         if self._win.getProperty("simplecachecleanbusy"): | ||||
|             return | ||||
|         self._win.setProperty("simplecachecleanbusy", "busy") | ||||
| 
 | ||||
|         query = "SELECT id, expires FROM simplecache" | ||||
|         for cache_data in self._execute_sql(query).fetchall(): | ||||
|             cache_id = cache_data[0] | ||||
|             cache_expires = cache_data[1] | ||||
| 
 | ||||
|             if self._exit or self._monitor.abortRequested(): | ||||
|                 return | ||||
| 
 | ||||
|             # always cleanup all memory objects on each interval | ||||
|             self._win.clearProperty(cache_id) | ||||
| 
 | ||||
|             # clean up db cache object only if expired | ||||
|             if cache_expires < cur_timestamp: | ||||
|                 query = 'DELETE FROM simplecache WHERE id = ?' | ||||
|                 self._execute_sql(query, (cache_id,)) | ||||
|                 self._log_msg("delete from db %s" % cache_id) | ||||
| 
 | ||||
|         # compact db | ||||
|         self._execute_sql("VACUUM") | ||||
| 
 | ||||
|         # remove task from list | ||||
|         self._busy_tasks.remove(__name__) | ||||
|         self._win.setProperty("simplecache.clean.lastexecuted", repr(cur_time)) | ||||
|         self._win.clearProperty("simplecachecleanbusy") | ||||
|         self._log_msg("Auto cleanup done") | ||||
| 
 | ||||
|     def _get_database(self): | ||||
|         '''get reference to our sqllite _database - performs basic integrity check''' | ||||
|         addon = xbmcaddon.Addon(self.addon_id) | ||||
|         dbpath = addon.getAddonInfo('profile') | ||||
|         dbfile = xbmcvfs.translatePath("%s/simplecache.db" % dbpath) | ||||
| 
 | ||||
|         if not xbmcvfs.exists(dbpath): | ||||
|             xbmcvfs.mkdirs(dbpath) | ||||
|         del addon | ||||
|         try: | ||||
|             connection = sqlite3.connect(dbfile, timeout=30, isolation_level=None) | ||||
|             connection.execute('SELECT * FROM simplecache LIMIT 1') | ||||
|             return connection | ||||
|         except Exception as error: | ||||
|             # our _database is corrupt or doesn't exist yet, we simply try to recreate it | ||||
|             if xbmcvfs.exists(dbfile): | ||||
|                 xbmcvfs.delete(dbfile) | ||||
|             try: | ||||
|                 connection = sqlite3.connect(dbfile, timeout=30, isolation_level=None) | ||||
|                 connection.execute( | ||||
|                     """CREATE TABLE IF NOT EXISTS simplecache( | ||||
|                     id TEXT UNIQUE, expires INTEGER, data TEXT, checksum INTEGER)""") | ||||
|                 return connection | ||||
|             except Exception as error: | ||||
|                 self._log_msg("Exception while initializing _database: %s" % str(error), xbmc.LOGWARNING) | ||||
|                 self.close() | ||||
|                 return None | ||||
| 
 | ||||
|     def _execute_sql(self, query, data=None): | ||||
|         '''little wrapper around execute and executemany to just retry a db command if db is locked''' | ||||
|         retries = 0 | ||||
|         result = None | ||||
|         error = None | ||||
|         # always use new db object because we need to be sure that data is available for other simplecache instances | ||||
|         with self._get_database() as _database: | ||||
|             while not retries == 10 and not self._monitor.abortRequested(): | ||||
|                 if self._exit: | ||||
|                     return None | ||||
|                 try: | ||||
|                     if isinstance(data, list): | ||||
|                         result = _database.executemany(query, data) | ||||
|                     elif data: | ||||
|                         result = _database.execute(query, data) | ||||
|                     else: | ||||
|                         result = _database.execute(query) | ||||
|                     return result | ||||
|                 except sqlite3.OperationalError as error: | ||||
|                     if "_database is locked" in error: | ||||
|                         self._log_msg("retrying DB commit...") | ||||
|                         retries += 1 | ||||
|                         self._monitor.waitForAbort(0.5) | ||||
|                     else: | ||||
|                         break | ||||
|                 except Exception as error: | ||||
|                     break | ||||
|             self._log_msg("_database ERROR ! -- %s" % str(error), xbmc.LOGWARNING) | ||||
|         return None | ||||
| 
 | ||||
|     @staticmethod | ||||
|     def _log_msg(msg, loglevel=xbmc.LOGDEBUG): | ||||
|         '''helper to send a message to the kodi log''' | ||||
|         xbmc.log("Skin Helper Simplecache --> %s" % msg, level=loglevel) | ||||
| 
 | ||||
|     @staticmethod | ||||
|     def _get_timestamp(date_time): | ||||
|         '''Converts a datetime object to unix timestamp''' | ||||
|         return int(time.mktime(date_time.timetuple())) | ||||
| 
 | ||||
|     def _get_checksum(self, stringinput): | ||||
|         '''get int checksum from string''' | ||||
|         if not stringinput and not self.global_checksum: | ||||
|             return 0 | ||||
|         if self.global_checksum: | ||||
|             stringinput = "%s-%s" %(self.global_checksum, stringinput) | ||||
|         else: | ||||
|             stringinput = str(stringinput) | ||||
|         return reduce(lambda x, y: x + y, map(ord, stringinput)) | ||||
| 
 | ||||
| 
 | ||||
| def use_cache(cache_days=14): | ||||
|     ''' | ||||
|         wrapper around our simple cache to use as decorator | ||||
|         Usage: define an instance of SimpleCache with name "cache" (self.cache) in your class | ||||
|         Any method that needs caching just add @use_cache as decorator | ||||
|         NOTE: use unnamed arguments for calling the method and named arguments for optional settings | ||||
|     ''' | ||||
|     def decorator(func): | ||||
|         '''our decorator''' | ||||
|         def decorated(*args, **kwargs): | ||||
|             '''process the original method and apply caching of the results''' | ||||
|             method_class = args[0] | ||||
|             method_class_name = method_class.__class__.__name__ | ||||
|             cache_str = "%s.%s" % (method_class_name, func.__name__) | ||||
|             # cache identifier is based on positional args only | ||||
|             # named args are considered optional and ignored | ||||
|             for item in args[1:]: | ||||
|                 cache_str += u".%s" % item | ||||
|             cache_str = cache_str.lower() | ||||
|             cachedata = method_class.cache.get(cache_str) | ||||
|             global_cache_ignore = False | ||||
|             try: | ||||
|                 global_cache_ignore = method_class.ignore_cache | ||||
|             except Exception: | ||||
|                 pass | ||||
|             if cachedata is not None and not kwargs.get("ignore_cache", False) and not global_cache_ignore: | ||||
|                 return cachedata | ||||
|             else: | ||||
|                 result = func(*args, **kwargs) | ||||
|                 method_class.cache.set(cache_str, result, expiration=datetime.timedelta(days=cache_days)) | ||||
|                 return result | ||||
|         return decorated | ||||
|     return decorator | ||||
							
								
								
									
										5
									
								
								resources/lib/deps/spotipy/__init__.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								resources/lib/deps/spotipy/__init__.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,5 @@ | |||
| from .cache_handler import *  # noqa | ||||
| from .client import *  # noqa | ||||
| from .exceptions import *  # noqa | ||||
| from .oauth2 import *  # noqa | ||||
| from .util import *  # noqa | ||||
							
								
								
									
										173
									
								
								resources/lib/deps/spotipy/cache_handler.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										173
									
								
								resources/lib/deps/spotipy/cache_handler.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,173 @@ | |||
| __all__ = [ | ||||
|     'CacheHandler', | ||||
|     'CacheFileHandler', | ||||
|     'DjangoSessionCacheHandler', | ||||
|     'FlaskSessionCacheHandler', | ||||
|     'MemoryCacheHandler'] | ||||
| 
 | ||||
| import errno | ||||
| import json | ||||
| import logging | ||||
| import os | ||||
| from spotipy.util import CLIENT_CREDS_ENV_VARS | ||||
| 
 | ||||
| logger = logging.getLogger(__name__) | ||||
| 
 | ||||
| 
 | ||||
| class CacheHandler(): | ||||
|     """ | ||||
|     An abstraction layer for handling the caching and retrieval of | ||||
|     authorization tokens. | ||||
| 
 | ||||
|     Custom extensions of this class must implement get_cached_token | ||||
|     and save_token_to_cache methods with the same input and output | ||||
|     structure as the CacheHandler class. | ||||
|     """ | ||||
| 
 | ||||
|     def get_cached_token(self): | ||||
|         """ | ||||
|         Get and return a token_info dictionary object. | ||||
|         """ | ||||
|         # return token_info | ||||
|         raise NotImplementedError() | ||||
| 
 | ||||
|     def save_token_to_cache(self, token_info): | ||||
|         """ | ||||
|         Save a token_info dictionary object to the cache and return None. | ||||
|         """ | ||||
|         raise NotImplementedError() | ||||
|         return None | ||||
| 
 | ||||
| 
 | ||||
| class CacheFileHandler(CacheHandler): | ||||
|     """ | ||||
|     Handles reading and writing cached Spotify authorization tokens | ||||
|     as json files on disk. | ||||
|     """ | ||||
| 
 | ||||
|     def __init__(self, | ||||
|                  cache_path=None, | ||||
|                  username=None, | ||||
|                  encoder_cls=None): | ||||
|         """ | ||||
|         Parameters: | ||||
|              * cache_path: May be supplied, will otherwise be generated | ||||
|                            (takes precedence over `username`) | ||||
|              * username: May be supplied or set as environment variable | ||||
|                          (will set `cache_path` to `.cache-{username}`) | ||||
|              * encoder_cls: May be supplied as a means of overwriting the | ||||
|                         default serializer used for writing tokens to disk | ||||
|         """ | ||||
|         self.encoder_cls = encoder_cls | ||||
|         if cache_path: | ||||
|             self.cache_path = cache_path | ||||
|         else: | ||||
|             cache_path = ".cache" | ||||
|             username = (username or os.getenv(CLIENT_CREDS_ENV_VARS["client_username"])) | ||||
|             if username: | ||||
|                 cache_path += "-" + str(username) | ||||
|             self.cache_path = cache_path | ||||
| 
 | ||||
|     def get_cached_token(self): | ||||
|         token_info = None | ||||
| 
 | ||||
|         try: | ||||
|             f = open(self.cache_path) | ||||
|             token_info_string = f.read() | ||||
|             f.close() | ||||
|             token_info = json.loads(token_info_string) | ||||
| 
 | ||||
|         except IOError as error: | ||||
|             if error.errno == errno.ENOENT: | ||||
|                 logger.debug("cache does not exist at: %s", self.cache_path) | ||||
|             else: | ||||
|                 logger.warning("Couldn't read cache at: %s", self.cache_path) | ||||
| 
 | ||||
|         return token_info | ||||
| 
 | ||||
|     def save_token_to_cache(self, token_info): | ||||
|         try: | ||||
|             f = open(self.cache_path, "w") | ||||
|             f.write(json.dumps(token_info, cls=self.encoder_cls)) | ||||
|             f.close() | ||||
|         except IOError: | ||||
|             logger.warning('Couldn\'t write token to cache at: %s', | ||||
|                            self.cache_path) | ||||
| 
 | ||||
| 
 | ||||
| class MemoryCacheHandler(CacheHandler): | ||||
|     """ | ||||
|     A cache handler that simply stores the token info in memory as an | ||||
|     instance attribute of this class. The token info will be lost when this | ||||
|     instance is freed. | ||||
|     """ | ||||
| 
 | ||||
|     def __init__(self, token_info=None): | ||||
|         """ | ||||
|         Parameters: | ||||
|             * token_info: The token info to store in memory. Can be None. | ||||
|         """ | ||||
|         self.token_info = token_info | ||||
| 
 | ||||
|     def get_cached_token(self): | ||||
|         return self.token_info | ||||
| 
 | ||||
|     def save_token_to_cache(self, token_info): | ||||
|         self.token_info = token_info | ||||
| 
 | ||||
| 
 | ||||
| class DjangoSessionCacheHandler(CacheHandler): | ||||
|     """ | ||||
|     A cache handler that stores the token info in the session framework | ||||
|     provided by Django. | ||||
| 
 | ||||
|     Read more at https://docs.djangoproject.com/en/3.2/topics/http/sessions/ | ||||
|     """ | ||||
| 
 | ||||
|     def __init__(self, request): | ||||
|         """ | ||||
|         Parameters: | ||||
|             * request: HttpRequest object provided by Django for every | ||||
|             incoming request | ||||
|         """ | ||||
|         self.request = request | ||||
| 
 | ||||
|     def get_cached_token(self): | ||||
|         token_info = None | ||||
|         try: | ||||
|             token_info = self.request.session['token_info'] | ||||
|         except KeyError: | ||||
|             logger.debug("Token not found in the session") | ||||
| 
 | ||||
|         return token_info | ||||
| 
 | ||||
|     def save_token_to_cache(self, token_info): | ||||
|         try: | ||||
|             self.request.session['token_info'] = token_info | ||||
|         except Exception as e: | ||||
|             logger.warning("Error saving token to cache: " + str(e)) | ||||
| 
 | ||||
| 
 | ||||
| class FlaskSessionCacheHandler(CacheHandler): | ||||
|     """ | ||||
|     A cache handler that stores the token info in the session framework | ||||
|     provided by flask. | ||||
|     """ | ||||
| 
 | ||||
|     def __init__(self, session): | ||||
|         self.session = session | ||||
| 
 | ||||
|     def get_cached_token(self): | ||||
|         token_info = None | ||||
|         try: | ||||
|             token_info = self.session["token_info"] | ||||
|         except KeyError: | ||||
|             logger.debug("Token not found in the session") | ||||
| 
 | ||||
|         return token_info | ||||
| 
 | ||||
|     def save_token_to_cache(self, token_info): | ||||
|         try: | ||||
|             self.session["token_info"] = token_info | ||||
|         except Exception as e: | ||||
|             logger.warning("Error saving token to cache: " + str(e)) | ||||
							
								
								
									
										2035
									
								
								resources/lib/deps/spotipy/client.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										2035
									
								
								resources/lib/deps/spotipy/client.py
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										16
									
								
								resources/lib/deps/spotipy/exceptions.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								resources/lib/deps/spotipy/exceptions.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,16 @@ | |||
| class SpotifyException(Exception): | ||||
| 
 | ||||
|     def __init__(self, http_status, code, msg, reason=None, headers=None): | ||||
|         self.http_status = http_status | ||||
|         self.code = code | ||||
|         self.msg = msg | ||||
|         self.reason = reason | ||||
|         # `headers` is used to support `Retry-After` in the event of a | ||||
|         # 429 status code. | ||||
|         if headers is None: | ||||
|             headers = {} | ||||
|         self.headers = headers | ||||
| 
 | ||||
|     def __str__(self): | ||||
|         return 'http status: {0}, code:{1} - {2}, reason: {3}'.format( | ||||
|             self.http_status, self.code, self.msg, self.reason) | ||||
							
								
								
									
										1308
									
								
								resources/lib/deps/spotipy/oauth2.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1308
									
								
								resources/lib/deps/spotipy/oauth2.py
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										135
									
								
								resources/lib/deps/spotipy/util.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										135
									
								
								resources/lib/deps/spotipy/util.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,135 @@ | |||
| # -*- coding: utf-8 -*- | ||||
| 
 | ||||
| """ Shows a user's playlists (need to be authenticated via oauth) """ | ||||
| 
 | ||||
| __all__ = ["CLIENT_CREDS_ENV_VARS", "prompt_for_user_token"] | ||||
| 
 | ||||
| import logging | ||||
| import os | ||||
| import warnings | ||||
| 
 | ||||
| import spotipy | ||||
| 
 | ||||
| LOGGER = logging.getLogger(__name__) | ||||
| 
 | ||||
| CLIENT_CREDS_ENV_VARS = { | ||||
|     "client_id": "SPOTIPY_CLIENT_ID", | ||||
|     "client_secret": "SPOTIPY_CLIENT_SECRET", | ||||
|     "client_username": "SPOTIPY_CLIENT_USERNAME", | ||||
|     "redirect_uri": "SPOTIPY_REDIRECT_URI", | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| def prompt_for_user_token( | ||||
|     username=None, | ||||
|     scope=None, | ||||
|     client_id=None, | ||||
|     client_secret=None, | ||||
|     redirect_uri=None, | ||||
|     cache_path=None, | ||||
|     oauth_manager=None, | ||||
|     show_dialog=False | ||||
| ): | ||||
|     warnings.warn( | ||||
|         "'prompt_for_user_token' is deprecated." | ||||
|         "Use the following instead: " | ||||
|         "    auth_manager=SpotifyOAuth(scope=scope)" | ||||
|         "    spotipy.Spotify(auth_manager=auth_manager)", | ||||
|         DeprecationWarning | ||||
|     ) | ||||
|     """ prompts the user to login if necessary and returns | ||||
|         the user token suitable for use with the spotipy.Spotify | ||||
|         constructor | ||||
| 
 | ||||
|         Parameters: | ||||
| 
 | ||||
|          - username - the Spotify username (optional) | ||||
|          - scope - the desired scope of the request (optional) | ||||
|          - client_id - the client id of your app (required) | ||||
|          - client_secret - the client secret of your app (required) | ||||
|          - redirect_uri - the redirect URI of your app (required) | ||||
|          - cache_path - path to location to save tokens (optional) | ||||
|          - oauth_manager - Oauth manager object (optional) | ||||
|          - show_dialog - If true, a login prompt always shows (optional, defaults to False) | ||||
| 
 | ||||
|     """ | ||||
|     if not oauth_manager: | ||||
|         if not client_id: | ||||
|             client_id = os.getenv("SPOTIPY_CLIENT_ID") | ||||
| 
 | ||||
|         if not client_secret: | ||||
|             client_secret = os.getenv("SPOTIPY_CLIENT_SECRET") | ||||
| 
 | ||||
|         if not redirect_uri: | ||||
|             redirect_uri = os.getenv("SPOTIPY_REDIRECT_URI") | ||||
| 
 | ||||
|         if not client_id: | ||||
|             LOGGER.warning( | ||||
|                 """ | ||||
|                 You need to set your Spotify API credentials. | ||||
|                 You can do this by setting environment variables like so: | ||||
| 
 | ||||
|                 export SPOTIPY_CLIENT_ID='your-spotify-client-id' | ||||
|                 export SPOTIPY_CLIENT_SECRET='your-spotify-client-secret' | ||||
|                 export SPOTIPY_REDIRECT_URI='your-app-redirect-url' | ||||
| 
 | ||||
|                 Get your credentials at | ||||
|                     https://developer.spotify.com/my-applications | ||||
|             """ | ||||
|             ) | ||||
|             raise spotipy.SpotifyException(550, -1, "no credentials set") | ||||
| 
 | ||||
|     sp_oauth = oauth_manager or spotipy.SpotifyOAuth( | ||||
|         client_id, | ||||
|         client_secret, | ||||
|         redirect_uri, | ||||
|         scope=scope, | ||||
|         cache_path=cache_path, | ||||
|         username=username, | ||||
|         show_dialog=show_dialog | ||||
|     ) | ||||
| 
 | ||||
|     # try to get a valid token for this user, from the cache, | ||||
|     # if not in the cache, then create a new (this will send | ||||
|     # the user to a web page where they can authorize this app) | ||||
| 
 | ||||
|     token_info = sp_oauth.validate_token(sp_oauth.cache_handler.get_cached_token()) | ||||
| 
 | ||||
|     if not token_info: | ||||
|         code = sp_oauth.get_auth_response() | ||||
|         token = sp_oauth.get_access_token(code, as_dict=False) | ||||
|     else: | ||||
|         return token_info["access_token"] | ||||
| 
 | ||||
|     # Auth'ed API request | ||||
|     if token: | ||||
|         return token | ||||
|     else: | ||||
|         return None | ||||
| 
 | ||||
| 
 | ||||
| def get_host_port(netloc): | ||||
|     if ":" in netloc: | ||||
|         host, port = netloc.split(":", 1) | ||||
|         port = int(port) | ||||
|     else: | ||||
|         host = netloc | ||||
|         port = None | ||||
| 
 | ||||
|     return host, port | ||||
| 
 | ||||
| 
 | ||||
| def normalize_scope(scope): | ||||
|     if scope: | ||||
|         if isinstance(scope, str): | ||||
|             scopes = scope.split(',') | ||||
|         elif isinstance(scope, list) or isinstance(scope, tuple): | ||||
|             scopes = scope | ||||
|         else: | ||||
|             raise Exception( | ||||
|                 "Unsupported scope value, please either provide a list of scopes, " | ||||
|                 "or a string of scopes separated by commas" | ||||
|             ) | ||||
|         return " ".join(sorted(scopes)) | ||||
|     else: | ||||
|         return None | ||||
							
								
								
									
										84
									
								
								resources/lib/http_video_player_setter.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								resources/lib/http_video_player_setter.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,84 @@ | |||
| import os | ||||
| from xml.etree import ElementTree | ||||
| 
 | ||||
| import xbmcvfs | ||||
| from xbmc import LOGDEBUG | ||||
| 
 | ||||
| from utils import ADDON_ID, log_msg | ||||
| 
 | ||||
| 
 | ||||
| class HttpVideoPlayerSetter: | ||||
|     def __init__(self): | ||||
|         self.__plugin_name = ADDON_ID | ||||
|         self.__player_rules_filename = xbmcvfs.translatePath( | ||||
|             f"special://masterprofile/playercorefactory.xml" | ||||
|         ) | ||||
| 
 | ||||
|     def set_http_rule(self) -> bool: | ||||
|         if not os.path.exists(self.__player_rules_filename): | ||||
|             self.__create_new_player_rules() | ||||
|             log_msg(f"Created a new file '{self.__player_rules_filename}' with a video http rule.") | ||||
|             return True | ||||
|         else: | ||||
|             if self.__add_http_rule(): | ||||
|                 log_msg(f"Added a video http rule to '{self.__player_rules_filename}'") | ||||
|                 return True | ||||
| 
 | ||||
|             log_msg( | ||||
|                 f"There is already a video http rule in '{self.__player_rules_filename}'." | ||||
|                 " Nothing to do.", | ||||
|                 LOGDEBUG, | ||||
|             ) | ||||
|             return False | ||||
| 
 | ||||
|     def __create_new_player_rules(self) -> None: | ||||
|         xml_str = f"""<?xml version='1.0' encoding='utf-8'?> | ||||
| <playercorefactory> | ||||
|   <!-- This file created by the '{self.__plugin_name}' addon. -->      | ||||
|   <rules name="system rules"> | ||||
|     <rule name="http" protocols="http" player="VideoPlayer" /> | ||||
|   </rules> | ||||
| </playercorefactory> | ||||
| """ | ||||
|         with open(self.__player_rules_filename, "w") as f: | ||||
|             f.write(xml_str) | ||||
| 
 | ||||
|     def __add_http_rule(self) -> bool: | ||||
|         class CommentedTreeBuilder(ElementTree.TreeBuilder): | ||||
|             def comment(self, data): | ||||
|                 self.start(ElementTree.Comment().tag, {}) | ||||
|                 self.data(data) | ||||
|                 self.end(ElementTree.Comment().tag) | ||||
| 
 | ||||
|         parser = ElementTree.XMLParser(target=CommentedTreeBuilder()) | ||||
|         tree = ElementTree.parse(self.__player_rules_filename, parser=parser) | ||||
|         root = tree.getroot() | ||||
| 
 | ||||
|         http_rule = root.findall("./rules/rule/[@protocols='http']") | ||||
|         if http_rule: | ||||
|             return False | ||||
| 
 | ||||
|         rules = root.find("./rules") | ||||
| 
 | ||||
|         attributes = { | ||||
|             "name": "http", | ||||
|             "protocols": "http", | ||||
|             "player": "VideoPlayer", | ||||
|         } | ||||
|         new_rule = ElementTree.Element("rule", attributes) | ||||
|         new_rule.tail = "\n\n" + "    " | ||||
|         rules.insert(0, new_rule) | ||||
| 
 | ||||
|         comment = ElementTree.Comment( | ||||
|             f" This http rule added by the '{self.__plugin_name}' addon. " | ||||
|         ) | ||||
|         comment.tail = "\n" + "    " | ||||
|         rules.insert(0, comment) | ||||
| 
 | ||||
|         xml_str = ElementTree.tostring(root, encoding="unicode", xml_declaration=True) | ||||
| 
 | ||||
|         with open(self.__player_rules_filename, "w") as f: | ||||
|             f.write(xml_str) | ||||
|             f.write("\n") | ||||
| 
 | ||||
|         return True | ||||
							
								
								
									
										34
									
								
								resources/lib/librespot/__init__.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								resources/lib/librespot/__init__.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,34 @@ | |||
| from __future__ import annotations | ||||
| from librespot.crypto import DiffieHellman | ||||
| from librespot.proto.Keyexchange_pb2 import BuildInfo, Platform, Product, ProductFlags | ||||
| from librespot.structure import Closeable, Runnable | ||||
| import platform | ||||
| 
 | ||||
| 
 | ||||
| class Version: | ||||
|     version_name = "0.0.9" | ||||
| 
 | ||||
|     @staticmethod | ||||
|     def platform() -> Platform: | ||||
|         if platform.system() == "Windows": | ||||
|             return Platform.PLATFORM_WIN32_X86 | ||||
|         if platform.system() == "Darwin": | ||||
|             return Platform.PLATFORM_OSX_X86 | ||||
|         return Platform.PLATFORM_LINUX_X86 | ||||
| 
 | ||||
|     @staticmethod | ||||
|     def version_string(): | ||||
|         return "librespot-python " + Version.version_name | ||||
| 
 | ||||
|     @staticmethod | ||||
|     def system_info_string(): | ||||
|         return Version.version_string() + \ | ||||
|                "; Python " + platform.python_version() + \ | ||||
|                "; " + platform.system() | ||||
| 
 | ||||
|     @staticmethod | ||||
|     def standard_build_info() -> BuildInfo: | ||||
|         return BuildInfo(product=Product.PRODUCT_CLIENT, | ||||
|                          product_flags=[ProductFlags.PRODUCT_FLAG_NONE], | ||||
|                          platform=Version.platform(), | ||||
|                          version=117300517) | ||||
							
								
								
									
										912
									
								
								resources/lib/librespot/audio/__init__.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										912
									
								
								resources/lib/librespot/audio/__init__.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,912 @@ | |||
| from __future__ import annotations | ||||
| from librespot import util | ||||
| from librespot.audio.decrypt import AesAudioDecrypt | ||||
| from librespot.audio.format import SuperAudioFormat | ||||
| from librespot.audio.storage import ChannelManager | ||||
| from librespot.cache import CacheManager | ||||
| from librespot.crypto import Packet | ||||
| from librespot.metadata import EpisodeId, PlayableId, TrackId | ||||
| from librespot.proto import Metadata_pb2 as Metadata, StorageResolve_pb2 as StorageResolve | ||||
| from librespot.structure import AudioDecrypt, AudioQualityPicker, Closeable, FeederException, GeneralAudioStream, GeneralWritableStream, HaltListener, NoopAudioDecrypt, PacketsReceiver | ||||
| import concurrent.futures | ||||
| import io | ||||
| import logging | ||||
| import math | ||||
| import queue | ||||
| import random | ||||
| import struct | ||||
| import threading | ||||
| import time | ||||
| import typing | ||||
| import urllib.parse | ||||
| 
 | ||||
| if typing.TYPE_CHECKING: | ||||
|     from librespot.core import Session | ||||
| 
 | ||||
| 
 | ||||
| class AbsChunkedInputStream(io.BytesIO, HaltListener): | ||||
|     chunk_exception = None | ||||
|     closed = False | ||||
|     max_chunk_tries = 128 | ||||
|     preload_ahead = 3 | ||||
|     preload_chunk_retries = 2 | ||||
|     retries: typing.List[int] | ||||
|     retry_on_chunk_error: bool | ||||
|     wait_lock: threading.Condition = threading.Condition() | ||||
|     wait_for_chunk = -1 | ||||
|     __decoded_length = 0 | ||||
|     __mark = 0 | ||||
|     __pos = 0 | ||||
| 
 | ||||
|     def __init__(self, retry_on_chunk_error: bool): | ||||
|         super().__init__() | ||||
|         self.retries = [0] * self.chunks() | ||||
|         self.retry_on_chunk_error = retry_on_chunk_error | ||||
| 
 | ||||
|     def is_closed(self) -> bool: | ||||
|         return self.closed | ||||
| 
 | ||||
|     def buffer(self) -> typing.List[bytes]: | ||||
|         raise NotImplementedError() | ||||
| 
 | ||||
|     def size(self) -> int: | ||||
|         raise NotImplementedError() | ||||
| 
 | ||||
|     def close(self) -> None: | ||||
|         self.closed = True | ||||
|         with self.wait_lock: | ||||
|             self.wait_lock.notify_all() | ||||
| 
 | ||||
|     def available(self): | ||||
|         return self.size() - self.__pos | ||||
| 
 | ||||
|     def mark_supported(self) -> bool: | ||||
|         return True | ||||
| 
 | ||||
|     def mark(self, read_ahead_limit: int) -> None: | ||||
|         self.__mark = self.__pos | ||||
| 
 | ||||
|     def reset(self) -> None: | ||||
|         self.__pos = self.__mark | ||||
| 
 | ||||
|     def pos(self) -> int: | ||||
|         return self.__pos | ||||
| 
 | ||||
|     def seek(self, where: int, **kwargs) -> None: | ||||
|         if where < 0: | ||||
|             raise TypeError() | ||||
|         if self.closed: | ||||
|             raise IOError("Stream is closed!") | ||||
|         self.__pos = where | ||||
|         self.check_availability(int(self.__pos / (128 * 1024)), False, False) | ||||
| 
 | ||||
|     def skip(self, n: int) -> int: | ||||
|         if n < 0: | ||||
|             raise TypeError() | ||||
|         if self.closed: | ||||
|             raise IOError("Stream is closed!") | ||||
|         k = self.size() - self.__pos | ||||
|         if n < k: | ||||
|             k = n | ||||
|         self.__pos += k | ||||
|         chunk = int(self.__pos / (128 * 1024)) | ||||
|         self.check_availability(chunk, False, False) | ||||
|         return k | ||||
| 
 | ||||
|     def requested_chunks(self) -> typing.List[bool]: | ||||
|         raise NotImplementedError() | ||||
| 
 | ||||
|     def available_chunks(self) -> typing.List[bool]: | ||||
|         raise NotImplementedError() | ||||
| 
 | ||||
|     def chunks(self) -> int: | ||||
|         raise NotImplementedError() | ||||
| 
 | ||||
|     def request_chunk_from_stream(self, index: int) -> None: | ||||
|         raise NotImplementedError() | ||||
| 
 | ||||
|     def should_retry(self, chunk: int) -> bool: | ||||
|         if self.retries[chunk] < 1: | ||||
|             return True | ||||
|         if self.retries[chunk] > self.max_chunk_tries: | ||||
|             return False | ||||
|         return self.retry_on_chunk_error | ||||
| 
 | ||||
|     def check_availability(self, chunk: int, wait: bool, halted: bool) -> None: | ||||
|         if halted and not wait: | ||||
|             raise TypeError() | ||||
|         if not self.requested_chunks()[chunk]: | ||||
|             self.request_chunk_from_stream(chunk) | ||||
|             self.requested_chunks()[chunk] = True | ||||
|         for i in range(chunk + 1, | ||||
|                        min(self.chunks() - 1, chunk + self.preload_ahead) + 1): | ||||
|             if (self.requested_chunks()[i] | ||||
|                     and self.retries[i] < self.preload_chunk_retries): | ||||
|                 self.request_chunk_from_stream(i) | ||||
|                 self.requested_chunks()[chunk] = True | ||||
|         if wait: | ||||
|             if self.available_chunks()[chunk]: | ||||
|                 return | ||||
|             retry = False | ||||
|             with self.wait_lock: | ||||
|                 if not halted: | ||||
|                     self.stream_read_halted(chunk, int(time.time() * 1000)) | ||||
|                 self.chunk_exception = None | ||||
|                 self.wait_for_chunk = chunk | ||||
|                 self.wait_lock.wait_for(lambda: self.available_chunks()[chunk]) | ||||
|                 if self.closed: | ||||
|                     return | ||||
|                 if self.chunk_exception is not None: | ||||
|                     if self.should_retry(chunk): | ||||
|                         retry = True | ||||
|                     else: | ||||
|                         raise AbsChunkedInputStream.ChunkException | ||||
|                 if not retry: | ||||
|                     self.stream_read_halted(chunk, int(time.time() * 1000)) | ||||
|             if retry: | ||||
|                 time.sleep(math.log10(self.retries[chunk])) | ||||
|                 self.check_availability(chunk, True, True) | ||||
| 
 | ||||
|     def read(self, __size: int = 0) -> bytes: | ||||
|         if self.closed: | ||||
|             raise IOError("Stream is closed!") | ||||
|         if __size <= 0: | ||||
|             if self.__pos == self.size(): | ||||
|                 return b"" | ||||
|             buffer = io.BytesIO() | ||||
|             total_size = self.size() | ||||
|             chunk = int(self.__pos / (128 * 1024)) | ||||
|             chunk_off = int(self.__pos % (128 * 1024)) | ||||
|             chunk_total = int(math.ceil(total_size / (128 * 1024))) | ||||
|             self.check_availability(chunk, True, False) | ||||
|             buffer.write(self.buffer()[chunk][chunk_off:]) | ||||
|             chunk += 1 | ||||
|             if chunk != chunk_total: | ||||
|                 while chunk <= chunk_total - 1: | ||||
|                     self.check_availability(chunk, True, False) | ||||
|                     buffer.write(self.buffer()[chunk]) | ||||
|                     chunk += 1 | ||||
|             buffer.seek(0) | ||||
|             self.__pos += buffer.getbuffer().nbytes | ||||
|             return buffer.read() | ||||
|         buffer = io.BytesIO() | ||||
|         chunk = int(self.__pos / (128 * 1024)) | ||||
|         chunk_off = int(self.__pos % (128 * 1024)) | ||||
|         chunk_end = int(__size / (128 * 1024)) | ||||
|         chunk_end_off = int(__size % (128 * 1024)) | ||||
|         if chunk_end > self.size(): | ||||
|             chunk_end = int(self.size() / (128 * 1024)) | ||||
|             chunk_end_off = int(self.size() % (128 * 1024)) | ||||
|         self.check_availability(chunk, True, False) | ||||
|         if chunk_off + __size > len(self.buffer()[chunk]): | ||||
|             buffer.write(self.buffer()[chunk][chunk_off:]) | ||||
|             chunk += 1 | ||||
|             while chunk <= chunk_end: | ||||
|                 self.check_availability(chunk, True, False) | ||||
|                 if chunk == chunk_end: | ||||
|                     buffer.write(self.buffer()[chunk][:chunk_end_off]) | ||||
|                 else: | ||||
|                     buffer.write(self.buffer()[chunk]) | ||||
|                 chunk += 1 | ||||
|         else: | ||||
|             buffer.write(self.buffer()[chunk][chunk_off:chunk_off + __size]) | ||||
|         buffer.seek(0) | ||||
|         self.__pos += buffer.getbuffer().nbytes | ||||
|         return buffer.read() | ||||
| 
 | ||||
|     def notify_chunk_available(self, index: int) -> None: | ||||
|         self.available_chunks()[index] = True | ||||
|         self.__decoded_length += len(self.buffer()[index]) | ||||
|         with self.wait_lock: | ||||
|             if index == self.wait_for_chunk and not self.closed: | ||||
|                 self.wait_for_chunk = -1 | ||||
|                 self.wait_lock.notify_all() | ||||
| 
 | ||||
|     def notify_chunk_error(self, index: int, ex): | ||||
|         self.available_chunks()[index] = False | ||||
|         self.requested_chunks()[index] = False | ||||
|         self.retries[index] += 1 | ||||
|         with self.wait_lock: | ||||
|             if index == self.wait_for_chunk and not self.closed: | ||||
|                 self.chunk_exception = ex | ||||
|                 self.wait_for_chunk = -1 | ||||
|                 self.wait_lock.notify_all() | ||||
| 
 | ||||
|     def decoded_length(self): | ||||
|         return self.__decoded_length | ||||
| 
 | ||||
|     class ChunkException(IOError): | ||||
| 
 | ||||
|         @staticmethod | ||||
|         def from_stream_error(stream_error: int): | ||||
|             return AbsChunkedInputStream \ | ||||
|                 .ChunkException("Failed due to stream error, code: {}".format(stream_error)) | ||||
| 
 | ||||
| 
 | ||||
| class AudioKeyManager(PacketsReceiver, Closeable): | ||||
|     audio_key_request_timeout = 20 | ||||
|     logger = logging.getLogger("Librespot:AudioKeyManager") | ||||
|     __callbacks: typing.Dict[int, Callback] = {} | ||||
|     __seq_holder = 0 | ||||
|     __seq_holder_lock = threading.Condition() | ||||
|     __session: Session | ||||
|     __zero_short = b"\x00\x00" | ||||
| 
 | ||||
|     def __init__(self, session: Session): | ||||
|         self.__session = session | ||||
| 
 | ||||
|     def dispatch(self, packet: Packet) -> None: | ||||
|         payload = io.BytesIO(packet.payload) | ||||
|         seq = struct.unpack(">i", payload.read(4))[0] | ||||
|         callback = self.__callbacks.get(seq) | ||||
|         if callback is None: | ||||
|             self.logger.warning( | ||||
|                 "Couldn't find callback for seq: {}".format(seq)) | ||||
|             return | ||||
|         if packet.is_cmd(Packet.Type.aes_key): | ||||
|             key = payload.read(16) | ||||
|             callback.key(key) | ||||
|         elif packet.is_cmd(Packet.Type.aes_key_error): | ||||
|             code = struct.unpack(">H", payload.read(2))[0] | ||||
|             callback.error(code) | ||||
|         else: | ||||
|             self.logger.warning( | ||||
|                 "Couldn't handle packet, cmd: {}, length: {}".format( | ||||
|                     packet.cmd, len(packet.payload))) | ||||
| 
 | ||||
|     def get_audio_key(self, | ||||
|                       gid: bytes, | ||||
|                       file_id: bytes, | ||||
|                       retry: bool = True) -> bytes: | ||||
|         seq: int | ||||
|         with self.__seq_holder_lock: | ||||
|             seq = self.__seq_holder | ||||
|             self.__seq_holder += 1 | ||||
|         out = io.BytesIO() | ||||
|         out.write(file_id) | ||||
|         out.write(gid) | ||||
|         out.write(struct.pack(">i", seq)) | ||||
|         out.write(self.__zero_short) | ||||
|         out.seek(0) | ||||
|         self.__session.send(Packet.Type.request_key, out.read()) | ||||
|         callback = AudioKeyManager.SyncCallback(self) | ||||
|         self.__callbacks[seq] = callback | ||||
|         key = callback.wait_response() | ||||
|         if key is None: | ||||
|             if retry: | ||||
|                 return self.get_audio_key(gid, file_id, False) | ||||
|             raise RuntimeError( | ||||
|                 "Failed fetching audio key! gid: {}, fileId: {}".format( | ||||
|                     util.bytes_to_hex(gid), util.bytes_to_hex(file_id))) | ||||
|         return key | ||||
| 
 | ||||
|     class Callback: | ||||
| 
 | ||||
|         def key(self, key: bytes) -> None: | ||||
|             raise NotImplementedError | ||||
| 
 | ||||
|         def error(self, code: int) -> None: | ||||
|             raise NotImplementedError | ||||
| 
 | ||||
|     class SyncCallback(Callback): | ||||
|         __audio_key_manager: AudioKeyManager | ||||
|         __reference = queue.Queue() | ||||
|         __reference_lock = threading.Condition() | ||||
| 
 | ||||
|         def __init__(self, audio_key_manager: AudioKeyManager): | ||||
|             self.__audio_key_manager = audio_key_manager | ||||
| 
 | ||||
|         def key(self, key: bytes) -> None: | ||||
|             with self.__reference_lock: | ||||
|                 self.__reference.put(key) | ||||
|                 self.__reference_lock.notify_all() | ||||
| 
 | ||||
|         def error(self, code: int) -> None: | ||||
|             self.__audio_key_manager.logger.fatal( | ||||
|                 "Audio key error, code: {}".format(code)) | ||||
|             with self.__reference_lock: | ||||
|                 self.__reference.put(None) | ||||
|                 self.__reference_lock.notify_all() | ||||
| 
 | ||||
|         def wait_response(self) -> bytes: | ||||
|             with self.__reference_lock: | ||||
|                 self.__reference_lock.wait( | ||||
|                     AudioKeyManager.audio_key_request_timeout) | ||||
|                 return self.__reference.get(block=False) | ||||
| 
 | ||||
| 
 | ||||
| class CdnFeedHelper: | ||||
|     _LOGGER: logging = logging.getLogger(__name__) | ||||
| 
 | ||||
|     @staticmethod | ||||
|     def get_url(resp: StorageResolve.StorageResolveResponse) -> str: | ||||
|         selected_url = random.choice(resp.cdnurl) | ||||
|         while "audio4-gm-fb" in selected_url or "audio-gm-fb" in selected_url: | ||||
|             selected_url = random.choice(resp.cdnurl) | ||||
|         return selected_url | ||||
| 
 | ||||
|     @staticmethod | ||||
|     def load_track( | ||||
|             session: Session, track: Metadata.Track, file: Metadata.AudioFile, | ||||
|             resp_or_url: typing.Union[StorageResolve.StorageResolveResponse, | ||||
|                                       str], preload: bool, | ||||
|             halt_listener: HaltListener) -> PlayableContentFeeder.LoadedStream: | ||||
|         if type(resp_or_url) is str: | ||||
|             url = resp_or_url | ||||
|         else: | ||||
|             url = CdnFeedHelper.get_url(resp_or_url) | ||||
|         start = int(time.time() * 1000) | ||||
|         key = session.audio_key().get_audio_key(track.gid, file.file_id) | ||||
|         audio_key_time = int(time.time() * 1000) - start | ||||
| 
 | ||||
|         streamer = session.cdn().stream_file(file, key, url, halt_listener) | ||||
|         input_stream = streamer.stream() | ||||
|         normalization_data = NormalizationData.read(input_stream) | ||||
|         if input_stream.skip(0xA7) != 0xA7: | ||||
|             raise IOError("Couldn't skip 0xa7 bytes!") | ||||
|         return PlayableContentFeeder.LoadedStream( | ||||
|             track, | ||||
|             streamer, | ||||
|             normalization_data, | ||||
|             PlayableContentFeeder.Metrics(file.file_id, preload, | ||||
|                                           -1 if preload else audio_key_time), | ||||
|         ) | ||||
| 
 | ||||
|     @staticmethod | ||||
|     def load_episode_external( | ||||
|             session: Session, episode: Metadata.Episode, | ||||
|             halt_listener: HaltListener) -> PlayableContentFeeder.LoadedStream: | ||||
|         resp = session.client().head(episode.external_url) | ||||
| 
 | ||||
|         if resp.status_code != 200: | ||||
|             CdnFeedHelper._LOGGER.warning("Couldn't resolve redirect!") | ||||
| 
 | ||||
|         url = resp.url | ||||
|         CdnFeedHelper._LOGGER.debug("Fetched external url for {}: {}".format( | ||||
|             util.bytes_to_hex(episode.gid), url)) | ||||
| 
 | ||||
|         streamer = session.cdn().stream_external_episode( | ||||
|             episode, url, halt_listener) | ||||
|         return PlayableContentFeeder.LoadedStream( | ||||
|             episode, | ||||
|             streamer, | ||||
|             None, | ||||
|             PlayableContentFeeder.Metrics(None, False, -1), | ||||
|         ) | ||||
| 
 | ||||
|     @staticmethod | ||||
|     def load_episode( | ||||
|         session: Session, | ||||
|         episode: Metadata.Episode, | ||||
|         file: Metadata.AudioFile, | ||||
|         resp_or_url: typing.Union[StorageResolve.StorageResolveResponse, str], | ||||
|         preload: bool, | ||||
|         halt_listener: HaltListener, | ||||
|     ) -> PlayableContentFeeder.LoadedStream: | ||||
|         if type(resp_or_url) is str: | ||||
|             url = resp_or_url | ||||
|         else: | ||||
|             url = CdnFeedHelper.get_url(resp_or_url) | ||||
|         start = int(time.time() * 1000) | ||||
|         key = session.audio_key().get_audio_key(episode.gid, file.file_id) | ||||
|         audio_key_time = int(time.time() * 1000) - start | ||||
| 
 | ||||
|         streamer = session.cdn().stream_file(file, key, url, halt_listener) | ||||
|         input_stream = streamer.stream() | ||||
|         normalization_data = NormalizationData.read(input_stream) | ||||
|         if input_stream.skip(0xA7) != 0xA7: | ||||
|             raise IOError("Couldn't skip 0xa7 bytes!") | ||||
|         return PlayableContentFeeder.LoadedStream( | ||||
|             episode, | ||||
|             streamer, | ||||
|             normalization_data, | ||||
|             PlayableContentFeeder.Metrics(file.file_id, preload, | ||||
|                                           -1 if preload else audio_key_time), | ||||
|         ) | ||||
| 
 | ||||
| 
 | ||||
| class CdnManager: | ||||
|     logger: logging = logging.getLogger("Librespot:CdnManager") | ||||
|     __session: Session | ||||
| 
 | ||||
|     def __init__(self, session: Session): | ||||
|         self.__session = session | ||||
| 
 | ||||
|     def get_head(self, file_id: bytes): | ||||
|         response = self.__session.client() \ | ||||
|             .get(self.__session.get_user_attribute("head-files-url", "https://heads-fa.spotify.com/head/{file_id}") | ||||
|                  .replace("{file_id}", util.bytes_to_hex(file_id))) | ||||
|         if response.status_code != 200: | ||||
|             raise IOError("{}".format(response.status_code)) | ||||
|         body = response.content | ||||
|         if body is None: | ||||
|             raise IOError("Response body is empty!") | ||||
|         return body | ||||
| 
 | ||||
|     def stream_external_episode(self, episode: Metadata.Episode, | ||||
|                                 external_url: str, | ||||
|                                 halt_listener: HaltListener): | ||||
|         return CdnManager.Streamer( | ||||
|             self.__session, | ||||
|             StreamId(episode=episode), | ||||
|             SuperAudioFormat.MP3, | ||||
|             CdnManager.CdnUrl(self, None, external_url), | ||||
|             self.__session.cache(), | ||||
|             NoopAudioDecrypt(), | ||||
|             halt_listener, | ||||
|         ) | ||||
| 
 | ||||
|     def stream_file(self, file: Metadata.AudioFile, key: bytes, url: str, | ||||
|                     halt_listener: HaltListener): | ||||
|         return CdnManager.Streamer( | ||||
|             self.__session, | ||||
|             StreamId(file=file), | ||||
|             SuperAudioFormat.get(file.format), | ||||
|             CdnManager.CdnUrl(self, file.file_id, url), | ||||
|             self.__session.cache(), | ||||
|             AesAudioDecrypt(key), | ||||
|             halt_listener, | ||||
|         ) | ||||
| 
 | ||||
|     def get_audio_url(self, file_id: bytes): | ||||
|         response = self.__session.api()\ | ||||
|             .send("GET", "/storage-resolve/files/audio/interactive/{}".format(util.bytes_to_hex(file_id)), None, None) | ||||
|         if response.status_code != 200: | ||||
|             raise IOError(response.status_code) | ||||
|         body = response.content | ||||
|         if body is None: | ||||
|             raise IOError("Response body is empty!") | ||||
|         proto = StorageResolve.StorageResolveResponse() | ||||
|         proto.ParseFromString(body) | ||||
|         if proto.result == StorageResolve.StorageResolveResponse.Result.CDN: | ||||
|             url = random.choice(proto.cdnurl) | ||||
|             self.logger.debug("Fetched CDN url for {}: {}".format( | ||||
|                 util.bytes_to_hex(file_id), url)) | ||||
|             return url | ||||
|         raise CdnManager.CdnException( | ||||
|             "Could not retrieve CDN url! result: {}".format(proto.result)) | ||||
| 
 | ||||
|     class CdnException(Exception): | ||||
|         pass | ||||
| 
 | ||||
|     class InternalResponse: | ||||
|         buffer: bytes | ||||
|         headers: typing.Dict[str, str] | ||||
| 
 | ||||
|         def __init__(self, buffer: bytes, headers: typing.Dict[str, str]): | ||||
|             self.buffer = buffer | ||||
|             self.headers = headers | ||||
| 
 | ||||
|     class CdnUrl: | ||||
|         __cdn_manager = None | ||||
|         __file_id: bytes | ||||
|         __expiration: int | ||||
|         url: str | ||||
| 
 | ||||
|         def __init__(self, cdn_manager, file_id: typing.Union[bytes, None], | ||||
|                      url: str): | ||||
|             self.__cdn_manager: CdnManager = cdn_manager | ||||
|             self.__file_id = file_id | ||||
|             self.set_url(url) | ||||
| 
 | ||||
|         def url(self): | ||||
|             if self.__expiration == -1: | ||||
|                 return self.url | ||||
|             if self.__expiration <= int(time.time() * 1000) + 5 * 60 * 1000: | ||||
|                 self.url = self.__cdn_manager.get_audio_url(self.__file_id) | ||||
|             return self.url | ||||
| 
 | ||||
|         def set_url(self, url: str): | ||||
|             self.url = url | ||||
|             if self.__file_id is not None: | ||||
|                 token_url = urllib.parse.urlparse(url) | ||||
|                 token_query = urllib.parse.parse_qs(token_url.query) | ||||
|                 token_list = token_query.get("__token__") | ||||
|                 try: | ||||
|                     token_str = str(token_list[0]) | ||||
|                 except TypeError: | ||||
|                     token_str = "" | ||||
|                 expires_list = token_query.get("Expires") | ||||
|                 try: | ||||
|                     expires_str = str(expires_list[0]) | ||||
|                 except TypeError: | ||||
|                     expires_str = "" | ||||
|                 if token_str != "None" and len(token_str) != 0: | ||||
|                     expire_at = None | ||||
|                     split = token_str.split("~") | ||||
|                     for s in split: | ||||
|                         try: | ||||
|                             i = s.index("=") | ||||
|                         except ValueError: | ||||
|                             continue | ||||
|                         if s[:i] == "exp": | ||||
|                             expire_at = int(s[i + 1:]) | ||||
|                             break | ||||
|                     if expire_at is None: | ||||
|                         self.__expiration = -1 | ||||
|                         self.__cdn_manager.logger.warning( | ||||
|                             "Invalid __token__ in CDN url: {}".format(url)) | ||||
|                         return | ||||
|                     self.__expiration = expire_at * 1000 | ||||
|                 elif expires_str != "None" and len(expires_str) != 0: | ||||
|                     expires_at = None | ||||
|                     expires_str = expires_str.split("~")[0] | ||||
|                     expires_at = int(expires_str) | ||||
|                     if expires_at is None: | ||||
|                         self.__expiration = -1 | ||||
|                         self.__cdn_manager.logger.warning("Invalid Expires param in CDN url: {}".format(url)) | ||||
|                         return | ||||
|                     self.__expiration = expires_at * 1000 | ||||
|                 else: | ||||
|                     try: | ||||
|                         i = token_url.query.index("_") | ||||
|                     except ValueError: | ||||
|                         self.__expiration = -1 | ||||
|                         self.__cdn_manager.logger \ | ||||
|                             .warning("Couldn't extract expiration, invalid parameter in CDN url: {}".format(url)) | ||||
|                         return | ||||
|                     self.__expiration = int(token_url.query[:i]) * 1000 | ||||
| 
 | ||||
|             else: | ||||
|                 self.__expiration = -1 | ||||
| 
 | ||||
|     class Streamer(GeneralAudioStream, GeneralWritableStream): | ||||
|         available: typing.List[bool] | ||||
|         buffer: typing.List[bytes] | ||||
|         chunks: int | ||||
|         executor_service = concurrent.futures.ThreadPoolExecutor() | ||||
|         halt_listener: HaltListener | ||||
|         requested: typing.List[bool] | ||||
|         size: int | ||||
|         __audio_format: SuperAudioFormat | ||||
|         __audio_decrypt: AudioDecrypt | ||||
|         __cdn_url: CdnManager.CdnUrl | ||||
|         __internal_stream: InternalStream | ||||
|         __session: Session | ||||
|         __stream_id: StreamId | ||||
| 
 | ||||
|         def __init__(self, session: Session, stream_id: StreamId, | ||||
|                      audio_format: SuperAudioFormat, | ||||
|                      cdn_url: CdnManager.CdnUrl, cache: CacheManager, | ||||
|                      audio_decrypt: AudioDecrypt, halt_listener: HaltListener): | ||||
|             self.__session = session | ||||
|             self.__stream_id = stream_id | ||||
|             self.__audio_format = audio_format | ||||
|             self.__audio_decrypt = audio_decrypt | ||||
|             self.__cdn_url = cdn_url | ||||
|             self.halt_listener = halt_listener | ||||
|             response = self.request(range_start=0, | ||||
|                                     range_end=ChannelManager.chunk_size - 1) | ||||
|             content_range = response.headers.get("Content-Range") | ||||
|             if content_range is None: | ||||
|                 raise IOError("Missing Content-Range header!") | ||||
|             split = content_range.split("/") | ||||
|             self.size = int(split[1]) | ||||
|             self.chunks = int(math.ceil(self.size / ChannelManager.chunk_size)) | ||||
|             first_chunk = response.buffer | ||||
|             self.available = [False for _ in range(self.chunks)] | ||||
|             self.requested = [False for _ in range(self.chunks)] | ||||
|             self.buffer = [b"" for _ in range(self.chunks)] | ||||
|             self.__internal_stream = CdnManager.Streamer.InternalStream( | ||||
|                 self, False) | ||||
|             self.requested[0] = True | ||||
|             self.write_chunk(first_chunk, 0, False) | ||||
| 
 | ||||
|         def write_chunk(self, chunk: bytes, chunk_index: int, | ||||
|                         cached: bool) -> None: | ||||
|             if self.__internal_stream.is_closed(): | ||||
|                 return | ||||
|             self.__session.logger.debug( | ||||
|                 "Chunk {}/{} completed, cached: {}, stream: {}".format( | ||||
|                     chunk_index + 1, self.chunks, cached, self.describe())) | ||||
|             self.buffer[chunk_index] = self.__audio_decrypt.decrypt_chunk( | ||||
|                 chunk_index, chunk) | ||||
|             self.__internal_stream.notify_chunk_available(chunk_index) | ||||
| 
 | ||||
|         def stream(self) -> AbsChunkedInputStream: | ||||
|             return self.__internal_stream | ||||
| 
 | ||||
|         def codec(self) -> SuperAudioFormat: | ||||
|             return self.__audio_format | ||||
| 
 | ||||
|         def describe(self) -> str: | ||||
|             if self.__stream_id.is_episode(): | ||||
|                 return "episode_gid: {}".format( | ||||
|                     self.__stream_id.get_episode_gid()) | ||||
|             return "file_id: {}".format(self.__stream_id.get_file_id()) | ||||
| 
 | ||||
|         def decrypt_time_ms(self) -> int: | ||||
|             return self.__audio_decrypt.decrypt_time_ms() | ||||
| 
 | ||||
|         def request_chunk(self, index: int) -> None: | ||||
|             response = self.request(index) | ||||
|             self.write_chunk(response.buffer, index, False) | ||||
| 
 | ||||
|         def request(self, chunk: int = None, range_start: int = None, range_end: int = None)\ | ||||
|                 -> CdnManager.InternalResponse: | ||||
|             if chunk is None and range_start is None and range_end is None: | ||||
|                 raise TypeError() | ||||
|             if chunk is not None: | ||||
|                 range_start = ChannelManager.chunk_size * chunk | ||||
|                 range_end = (chunk + 1) * ChannelManager.chunk_size - 1 | ||||
|             response = self.__session.client().get( | ||||
|                 self.__cdn_url.url, | ||||
|                 headers={ | ||||
|                     "Range": "bytes={}-{}".format(range_start, range_end) | ||||
|                 }, | ||||
|             ) | ||||
|             if response.status_code != 206: | ||||
|                 raise IOError(response.status_code) | ||||
|             body = response.content | ||||
|             if body is None: | ||||
|                 raise IOError("Response body is empty!") | ||||
|             return CdnManager.InternalResponse(body, dict(response.headers)) | ||||
| 
 | ||||
|         class InternalStream(AbsChunkedInputStream): | ||||
|             streamer: CdnManager.Streamer | ||||
| 
 | ||||
|             def __init__(self, streamer, retry_on_chunk_error: bool): | ||||
|                 self.streamer: CdnManager.Streamer = streamer | ||||
|                 super().__init__(retry_on_chunk_error) | ||||
| 
 | ||||
|             def buffer(self) -> typing.List[bytes]: | ||||
|                 return self.streamer.buffer | ||||
| 
 | ||||
|             def size(self) -> int: | ||||
|                 return self.streamer.size | ||||
| 
 | ||||
|             def close(self) -> None: | ||||
|                 super().close() | ||||
|                 del self.streamer.buffer | ||||
| 
 | ||||
|             def requested_chunks(self) -> typing.List[bool]: | ||||
|                 return self.streamer.requested | ||||
| 
 | ||||
|             def available_chunks(self) -> typing.List[bool]: | ||||
|                 return self.streamer.available | ||||
| 
 | ||||
|             def chunks(self) -> int: | ||||
|                 return self.streamer.chunks | ||||
| 
 | ||||
|             def request_chunk_from_stream(self, index: int) -> None: | ||||
|                 self.streamer.executor_service \ | ||||
|                     .submit(lambda: self.streamer.request_chunk(index)) | ||||
| 
 | ||||
|             def stream_read_halted(self, chunk: int, _time: int) -> None: | ||||
|                 if self.streamer.halt_listener is not None: | ||||
|                     self.streamer.executor_service\ | ||||
|                         .submit(lambda: self.streamer.halt_listener.stream_read_halted(chunk, _time)) | ||||
| 
 | ||||
|             def stream_read_resumed(self, chunk: int, _time: int) -> None: | ||||
|                 if self.streamer.halt_listener is not None: | ||||
|                     self.streamer.executor_service \ | ||||
|                         .submit(lambda: self.streamer.halt_listener.stream_read_resumed(chunk, _time)) | ||||
| 
 | ||||
| 
 | ||||
| class NormalizationData: | ||||
|     _LOGGER: logging = logging.getLogger(__name__) | ||||
|     track_gain_db: float | ||||
|     track_peak: float | ||||
|     album_gain_db: float | ||||
|     album_peak: float | ||||
| 
 | ||||
|     def __init__(self, track_gain_db: float, track_peak: float, | ||||
|                  album_gain_db: float, album_peak: float): | ||||
|         self.track_gain_db = track_gain_db | ||||
|         self.track_peak = track_peak | ||||
|         self.album_gain_db = album_gain_db | ||||
|         self.album_peak = album_peak | ||||
| 
 | ||||
|         self._LOGGER.debug( | ||||
|             "Loaded normalization data, track_gain: {}, track_peak: {}, album_gain: {}, album_peak: {}" | ||||
|             .format(track_gain_db, track_peak, album_gain_db, album_peak)) | ||||
| 
 | ||||
|     @staticmethod | ||||
|     def read(input_stream: AbsChunkedInputStream) -> NormalizationData: | ||||
|         input_stream.seek(144) | ||||
|         data = input_stream.read(4 * 4) | ||||
|         input_stream.seek(0) | ||||
|         buffer = io.BytesIO(data) | ||||
|         return NormalizationData( | ||||
|             struct.unpack("<f", buffer.read(4))[0], | ||||
|             struct.unpack("<f", buffer.read(4))[0], | ||||
|             struct.unpack("<f", buffer.read(4))[0], | ||||
|             struct.unpack("<f", buffer.read(4))[0]) | ||||
| 
 | ||||
|     def get_factor(self, normalisation_pregain) -> float: | ||||
|         normalisation_factor = float( | ||||
|             math.pow(10, (self.track_gain_db + normalisation_pregain) / 20)) | ||||
|         if normalisation_factor * self.track_peak > 1: | ||||
|             self._LOGGER \ | ||||
|                 .warning("Reducing normalisation factor to prevent clipping. Please add negative pregain to avoid.") | ||||
|             normalisation_factor = 1 / self.track_peak | ||||
|         return normalisation_factor | ||||
| 
 | ||||
| 
 | ||||
| class PlayableContentFeeder: | ||||
|     logger = logging.getLogger("Librespot:PlayableContentFeeder") | ||||
|     storage_resolve_interactive = "/storage-resolve/files/audio/interactive/{}" | ||||
|     storage_resolve_interactive_prefetch = "/storage-resolve/files/audio/interactive_prefetch/{}" | ||||
|     __session: Session | ||||
| 
 | ||||
|     def __init__(self, session: Session): | ||||
|         self.__session = session | ||||
| 
 | ||||
|     def load(self, playable_id: PlayableId, | ||||
|              audio_quality_picker: AudioQualityPicker, preload: bool, | ||||
|              halt_listener: typing.Union[HaltListener, None]): | ||||
|         if type(playable_id) is TrackId: | ||||
|             return self.load_track(playable_id, audio_quality_picker, preload, | ||||
|                                    halt_listener) | ||||
|         if type(playable_id) is EpisodeId: | ||||
|             return self.load_episode(playable_id, audio_quality_picker, | ||||
|                                      preload, halt_listener) | ||||
|         raise TypeError("Unknown content: {}".format(playable_id)) | ||||
| 
 | ||||
|     def load_stream(self, file: Metadata.AudioFile, track: Metadata.Track, | ||||
|                     episode: Metadata.Episode, preload: bool, | ||||
|                     halt_lister: HaltListener): | ||||
|         if track is None and episode is None: | ||||
|             raise RuntimeError() | ||||
|         response = self.resolve_storage_interactive(file.file_id, preload) | ||||
|         if response.result == StorageResolve.StorageResolveResponse.Result.CDN: | ||||
|             if track is not None: | ||||
|                 return CdnFeedHelper.load_track(self.__session, track, file, | ||||
|                                                 response, preload, halt_lister) | ||||
|             return CdnFeedHelper.load_episode(self.__session, episode, file, | ||||
|                                               response, preload, halt_lister) | ||||
|         if response.result == StorageResolve.StorageResolveResponse.Result.STORAGE: | ||||
|             if track is None: | ||||
|                 pass | ||||
|         elif response.result == StorageResolve.StorageResolveResponse.Result.RESTRICTED: | ||||
|             raise RuntimeError("Content is restricted!") | ||||
|         elif response.result == StorageResolve.StorageResolveResponse.Response.UNRECOGNIZED: | ||||
|             raise RuntimeError("Content is unrecognized!") | ||||
|         else: | ||||
|             raise RuntimeError("Unknown result: {}".format(response.result)) | ||||
| 
 | ||||
|     def load_episode(self, episode_id: EpisodeId, | ||||
|                      audio_quality_picker: AudioQualityPicker, preload: bool, | ||||
|                      halt_listener: HaltListener) -> LoadedStream: | ||||
|         episode = self.__session.api().get_metadata_4_episode(episode_id) | ||||
|         if episode.external_url: | ||||
|             return CdnFeedHelper.load_episode_external(self.__session, episode, | ||||
|                                                        halt_listener) | ||||
|         file = audio_quality_picker.get_file(episode.audio) | ||||
|         if file is None: | ||||
|             self.logger.fatal( | ||||
|                 "Couldn't find any suitable audio file, available: {}".format( | ||||
|                     episode.audio)) | ||||
|         return self.load_stream(file, None, episode, preload, halt_listener) | ||||
| 
 | ||||
|     def load_track(self, track_id_or_track: typing.Union[TrackId, | ||||
|                                                          Metadata.Track], | ||||
|                    audio_quality_picker: AudioQualityPicker, preload: bool, | ||||
|                    halt_listener: HaltListener): | ||||
|         if type(track_id_or_track) is TrackId: | ||||
|             original = self.__session.api().get_metadata_4_track( | ||||
|                 track_id_or_track) | ||||
|             track = self.pick_alternative_if_necessary(original) | ||||
|             if track is None: | ||||
|                 raise RuntimeError("Cannot get alternative track") | ||||
|         else: | ||||
|             track = track_id_or_track | ||||
|         file = audio_quality_picker.get_file(track.file) | ||||
|         if file is None: | ||||
|             self.logger.fatal( | ||||
|                 "Couldn't find any suitable audio file, available: {}".format( | ||||
|                     track.file)) | ||||
|             raise FeederException() | ||||
|         return self.load_stream(file, track, None, preload, halt_listener) | ||||
| 
 | ||||
|     def pick_alternative_if_necessary( | ||||
|             self, track: Metadata.Track) -> typing.Union[Metadata.Track, None]: | ||||
|         if len(track.file) > 0: | ||||
|             return track | ||||
|         for alt in track.alternative: | ||||
|             if len(alt.file) > 0: | ||||
|                 return Metadata.Track( | ||||
|                     gid=track.gid, | ||||
|                     name=track.name, | ||||
|                     album=track.album, | ||||
|                     artist=track.artist, | ||||
|                     number=track.number, | ||||
|                     disc_number=track.disc_number, | ||||
|                     duration=track.duration, | ||||
|                     popularity=track.popularity, | ||||
|                     explicit=track.explicit, | ||||
|                     external_id=track.external_id, | ||||
|                     restriction=track.restriction, | ||||
|                     file=alt.file, | ||||
|                     sale_period=track.sale_period, | ||||
|                     preview=track.preview, | ||||
|                     tags=track.tags, | ||||
|                     earliest_live_timestamp=track.earliest_live_timestamp, | ||||
|                     has_lyrics=track.has_lyrics, | ||||
|                     availability=track.availability, | ||||
|                     licensor=track.licensor) | ||||
|         return None | ||||
| 
 | ||||
|     def resolve_storage_interactive( | ||||
|             self, file_id: bytes, | ||||
|             preload: bool) -> StorageResolve.StorageResolveResponse: | ||||
|         resp = self.__session.api().send( | ||||
|             "GET", | ||||
|             (self.storage_resolve_interactive_prefetch | ||||
|              if preload else self.storage_resolve_interactive).format( | ||||
|                  util.bytes_to_hex(file_id)), | ||||
|             None, | ||||
|             None, | ||||
|         ) | ||||
|         if resp.status_code != 200: | ||||
|             raise RuntimeError(resp.status_code) | ||||
|         body = resp.content | ||||
|         if body is None: | ||||
|             raise RuntimeError("Response body is empty!") | ||||
|         storage_resolve_response = StorageResolve.StorageResolveResponse() | ||||
|         storage_resolve_response.ParseFromString(body) | ||||
|         return storage_resolve_response | ||||
| 
 | ||||
|     class LoadedStream: | ||||
|         episode: Metadata.Episode | ||||
|         track: Metadata.Track | ||||
|         input_stream: GeneralAudioStream | ||||
|         normalization_data: NormalizationData | ||||
|         metrics: PlayableContentFeeder.Metrics | ||||
| 
 | ||||
|         def __init__(self, track_or_episode: typing.Union[Metadata.Track, | ||||
|                                                           Metadata.Episode], | ||||
|                      input_stream: GeneralAudioStream, | ||||
|                      normalization_data: typing.Union[NormalizationData, None], | ||||
|                      metrics: PlayableContentFeeder.Metrics): | ||||
|             if type(track_or_episode) is Metadata.Track: | ||||
|                 self.track = track_or_episode | ||||
|                 self.episode = None | ||||
|             elif type(track_or_episode) is Metadata.Episode: | ||||
|                 self.track = None | ||||
|                 self.episode = track_or_episode | ||||
|             else: | ||||
|                 raise TypeError() | ||||
|             self.input_stream = input_stream | ||||
|             self.normalization_data = normalization_data | ||||
|             self.metrics = metrics | ||||
| 
 | ||||
|     class Metrics: | ||||
|         file_id: str | ||||
|         preloaded_audio_key: bool | ||||
|         audio_key_time: int | ||||
| 
 | ||||
|         def __init__(self, file_id: typing.Union[bytes, None], | ||||
|                      preloaded_audio_key: bool, audio_key_time: int): | ||||
|             self.file_id = None if file_id is None else util.bytes_to_hex( | ||||
|                 file_id) | ||||
|             self.preloaded_audio_key = preloaded_audio_key | ||||
|             self.audio_key_time = audio_key_time | ||||
|             if preloaded_audio_key and audio_key_time != -1: | ||||
|                 raise RuntimeError() | ||||
| 
 | ||||
| 
 | ||||
| class StreamId: | ||||
|     file_id: bytes | ||||
|     episode_gid: bytes | ||||
| 
 | ||||
|     def __init__(self, | ||||
|                  file: Metadata.AudioFile = None, | ||||
|                  episode: Metadata.Episode = None): | ||||
|         if file is None and episode is None: | ||||
|             return | ||||
|         self.file_id = None if file is None else file.file_id | ||||
|         self.episode_gid = None if episode is None else episode.gid | ||||
| 
 | ||||
|     def get_file_id(self): | ||||
|         if self.file_id is None: | ||||
|             raise RuntimeError("Not a file!") | ||||
|         return util.bytes_to_hex(self.file_id) | ||||
| 
 | ||||
|     def is_episode(self): | ||||
|         return self.episode_gid is not None | ||||
| 
 | ||||
|     def get_episode_gid(self): | ||||
|         if self.episode_gid is None: | ||||
|             raise RuntimeError("Not an episode!") | ||||
|         return util.bytes_to_hex(self.episode_gid) | ||||
							
								
								
									
										81
									
								
								resources/lib/librespot/audio/decoders.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								resources/lib/librespot/audio/decoders.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,81 @@ | |||
| from __future__ import annotations | ||||
| from librespot.audio import SuperAudioFormat | ||||
| from librespot.proto import Metadata_pb2 as Metadata | ||||
| from librespot.proto.Metadata_pb2 import AudioFile | ||||
| from librespot.structure import AudioQualityPicker | ||||
| import enum | ||||
| import logging | ||||
| import typing | ||||
| 
 | ||||
| 
 | ||||
| class AudioQuality(enum.Enum): | ||||
|     NORMAL = 0x00 | ||||
|     HIGH = 0x01 | ||||
|     VERY_HIGH = 0x02 | ||||
| 
 | ||||
|     @staticmethod | ||||
|     def get_quality(audio_format: AudioFile.Format) -> AudioQuality: | ||||
|         if audio_format in [ | ||||
|                 AudioFile.MP3_96, | ||||
|                 AudioFile.OGG_VORBIS_96, | ||||
|                 AudioFile.AAC_24_NORM, | ||||
|         ]: | ||||
|             return AudioQuality.NORMAL | ||||
|         if audio_format in [ | ||||
|                 AudioFile.MP3_160, | ||||
|                 AudioFile.MP3_160_ENC, | ||||
|                 AudioFile.OGG_VORBIS_160, | ||||
|                 AudioFile.AAC_24, | ||||
|         ]: | ||||
|             return AudioQuality.HIGH | ||||
|         if audio_format in [ | ||||
|                 AudioFile.MP3_320, | ||||
|                 AudioFile.MP3_256, | ||||
|                 AudioFile.OGG_VORBIS_320, | ||||
|                 AudioFile.AAC_48, | ||||
|         ]: | ||||
|             return AudioQuality.VERY_HIGH | ||||
|         raise RuntimeError("Unknown format: {}".format(format)) | ||||
| 
 | ||||
|     def get_matches(self, | ||||
|                     files: typing.List[AudioFile]) -> typing.List[AudioFile]: | ||||
|         file_list = [] | ||||
|         for file in files: | ||||
|             if hasattr(file, "format") and AudioQuality.get_quality( | ||||
|                     file.format) == self: | ||||
|                 file_list.append(file) | ||||
|         return file_list | ||||
| 
 | ||||
| 
 | ||||
| class VorbisOnlyAudioQuality(AudioQualityPicker): | ||||
|     logger = logging.getLogger("Librespot:Player:VorbisOnlyAudioQuality") | ||||
|     preferred: AudioQuality | ||||
| 
 | ||||
|     def __init__(self, preferred: AudioQuality): | ||||
|         self.preferred = preferred | ||||
| 
 | ||||
|     @staticmethod | ||||
|     def get_vorbis_file(files: typing.List[Metadata.AudioFile]): | ||||
|         for file in files: | ||||
|             if file.HasField("format") and SuperAudioFormat.get( | ||||
|                     file.format) == SuperAudioFormat.VORBIS: | ||||
|                 return file | ||||
|         return None | ||||
| 
 | ||||
|     def get_file(self, files: typing.List[Metadata.AudioFile]): | ||||
|         matches: typing.List[Metadata.AudioFile] = self.preferred.get_matches( | ||||
|             files) | ||||
|         vorbis: Metadata.AudioFile = VorbisOnlyAudioQuality.get_vorbis_file( | ||||
|             matches) | ||||
|         if vorbis is None: | ||||
|             vorbis: Metadata.AudioFile = VorbisOnlyAudioQuality.get_vorbis_file( | ||||
|                 files) | ||||
|             if vorbis is not None: | ||||
|                 self.logger.warning( | ||||
|                     "Using {} because preferred {} couldn't be found.".format( | ||||
|                         Metadata.AudioFile.Format.Name(vorbis.format), | ||||
|                         self.preferred)) | ||||
|             else: | ||||
|                 self.logger.fatal( | ||||
|                     "Couldn't find any Vorbis file, available: {}") | ||||
|         return vorbis | ||||
							
								
								
									
										45
									
								
								resources/lib/librespot/audio/decrypt.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								resources/lib/librespot/audio/decrypt.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,45 @@ | |||
| from __future__ import annotations | ||||
| from Cryptodome.Cipher import AES | ||||
| from Cryptodome.Util import Counter | ||||
| from librespot.audio.storage import ChannelManager | ||||
| from librespot.structure import AudioDecrypt | ||||
| import io | ||||
| import time | ||||
| 
 | ||||
| 
 | ||||
| class AesAudioDecrypt(AudioDecrypt): | ||||
|     audio_aes_iv = b'r\xe0g\xfb\xdd\xcb\xcfw\xeb\xe8\xbcd?c\r\x93' | ||||
|     cipher = None | ||||
|     decrypt_count = 0 | ||||
|     decrypt_total_time = 0 | ||||
|     iv_int = int.from_bytes(audio_aes_iv, "big") | ||||
|     iv_diff = 0x100 | ||||
|     key: bytes | ||||
| 
 | ||||
|     def __init__(self, key: bytes): | ||||
|         self.key = key | ||||
| 
 | ||||
|     def decrypt_chunk(self, chunk_index: int, buffer: bytes): | ||||
|         new_buffer = io.BytesIO() | ||||
|         iv = self.iv_int + int(ChannelManager.chunk_size * chunk_index / 16) | ||||
|         start = time.time_ns() | ||||
|         for i in range(0, len(buffer), 4096): | ||||
|             cipher = AES.new(key=self.key, | ||||
|                              mode=AES.MODE_CTR, | ||||
|                              counter=Counter.new(128, initial_value=iv)) | ||||
|             count = min(4096, len(buffer) - i) | ||||
|             decrypted_buffer = cipher.decrypt(buffer[i:i + count]) | ||||
|             new_buffer.write(decrypted_buffer) | ||||
|             if count != len(decrypted_buffer): | ||||
|                 raise RuntimeError( | ||||
|                     "Couldn't process all data, actual: {}, expected: {}". | ||||
|                     format(len(decrypted_buffer), count)) | ||||
|             iv += self.iv_diff | ||||
|         self.decrypt_total_time += time.time_ns() - start | ||||
|         self.decrypt_count += 1 | ||||
|         new_buffer.seek(0) | ||||
|         return new_buffer.read() | ||||
| 
 | ||||
|     def decrypt_time_ms(self): | ||||
|         return 0 if self.decrypt_count == 0 else int( | ||||
|             (self.decrypt_total_time / self.decrypt_count) / 1000000) | ||||
							
								
								
									
										32
									
								
								resources/lib/librespot/audio/format.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								resources/lib/librespot/audio/format.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,32 @@ | |||
| from librespot.proto import Metadata_pb2 as Metadata | ||||
| import enum | ||||
| 
 | ||||
| 
 | ||||
| class SuperAudioFormat(enum.Enum): | ||||
|     MP3 = 0x00 | ||||
|     VORBIS = 0x01 | ||||
|     AAC = 0x02 | ||||
| 
 | ||||
|     @staticmethod | ||||
|     def get(audio_format: Metadata.AudioFile.Format): | ||||
|         if audio_format in [ | ||||
|                 Metadata.AudioFile.Format.OGG_VORBIS_96, | ||||
|                 Metadata.AudioFile.Format.OGG_VORBIS_160, | ||||
|                 Metadata.AudioFile.Format.OGG_VORBIS_320, | ||||
|         ]: | ||||
|             return SuperAudioFormat.VORBIS | ||||
|         if audio_format in [ | ||||
|                 Metadata.AudioFile.Format.MP3_256, | ||||
|                 Metadata.AudioFile.Format.MP3_320, | ||||
|                 Metadata.AudioFile.Format.MP3_160, | ||||
|                 Metadata.AudioFile.Format.MP3_96, | ||||
|                 Metadata.AudioFile.Format.MP3_160_ENC, | ||||
|         ]: | ||||
|             return SuperAudioFormat.MP3 | ||||
|         if audio_format in [ | ||||
|                 Metadata.AudioFile.Format.AAC_24, | ||||
|                 Metadata.AudioFile.Format.AAC_48, | ||||
|                 Metadata.AudioFile.Format.AAC_24_NORM, | ||||
|         ]: | ||||
|             return SuperAudioFormat.AAC | ||||
|         raise RuntimeError("Unknown audio format: {}".format(audio_format)) | ||||
							
								
								
									
										139
									
								
								resources/lib/librespot/audio/storage.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										139
									
								
								resources/lib/librespot/audio/storage.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,139 @@ | |||
| from __future__ import annotations | ||||
| from librespot import util | ||||
| from librespot.crypto import Packet | ||||
| from librespot.proto.Metadata_pb2 import AudioFile | ||||
| from librespot.structure import Closeable, PacketsReceiver | ||||
| import concurrent.futures | ||||
| import io | ||||
| import logging | ||||
| import queue | ||||
| import struct | ||||
| import threading | ||||
| import typing | ||||
| 
 | ||||
| if typing.TYPE_CHECKING: | ||||
|     from librespot.core import Session | ||||
| 
 | ||||
| 
 | ||||
| class ChannelManager(Closeable, PacketsReceiver): | ||||
|     channels: typing.Dict[int, Channel] = {} | ||||
|     chunk_size = 128 * 1024 | ||||
|     executor_service = concurrent.futures.ThreadPoolExecutor() | ||||
|     logger = logging.getLogger("Librespot:ChannelManager") | ||||
|     seq_holder = 0 | ||||
|     seq_holder_lock = threading.Condition() | ||||
|     __session: Session = None | ||||
| 
 | ||||
|     def __init__(self, session: Session): | ||||
|         self.__session = session | ||||
| 
 | ||||
|     def request_chunk(self, file_id: bytes, index: int, file: AudioFile): | ||||
|         start = int(index * self.chunk_size / 4) | ||||
|         end = int((index + 1) * self.chunk_size / 4) | ||||
|         channel = ChannelManager.Channel(self, file, index) | ||||
|         self.channels[channel.chunk_id] = channel | ||||
|         out = io.BytesIO() | ||||
|         out.write(struct.pack(">H", channel.chunk_id)) | ||||
|         out.write(struct.pack(">i", 0x00000000)) | ||||
|         out.write(struct.pack(">i", 0x00000000)) | ||||
|         out.write(struct.pack(">i", 0x00004E20)) | ||||
|         out.write(struct.pack(">i", 0x00030D40)) | ||||
|         out.write(file_id) | ||||
|         out.write(struct.pack(">i", start)) | ||||
|         out.write(struct.pack(">i", end)) | ||||
|         out.seek(0) | ||||
|         self.__session.send(Packet.Type.stream_chunk, out.read()) | ||||
| 
 | ||||
|     def dispatch(self, packet: Packet) -> None: | ||||
|         payload = io.BytesIO(packet.payload) | ||||
|         if packet.is_cmd(Packet.Type.stream_chunk_res): | ||||
|             chunk_id = struct.unpack(">H", payload.read(2))[0] | ||||
|             channel = self.channels.get(chunk_id) | ||||
|             if channel is None: | ||||
|                 self.logger.warning( | ||||
|                     "Couldn't find channel, id: {}, received: {}".format( | ||||
|                         chunk_id, len(packet.payload))) | ||||
|                 return | ||||
|             channel.add_to_queue(payload) | ||||
|         elif packet.is_cmd(Packet.Type.channel_error): | ||||
|             chunk_id = struct.unpack(">H", payload.read(2))[0] | ||||
|             channel = self.channels.get(chunk_id) | ||||
|             if channel is None: | ||||
|                 self.logger.warning( | ||||
|                     "Dropping channel error, id: {}, code: {}".format( | ||||
|                         chunk_id, | ||||
|                         struct.unpack(">H", payload.read(2))[0])) | ||||
|                 return | ||||
|             channel.stream_error(struct.unpack(">H", payload.read(2))[0]) | ||||
|         else: | ||||
|             self.logger.warning( | ||||
|                 "Couldn't handle packet, cmd: {}, payload: {}".format( | ||||
|                     packet.cmd, util.bytes_to_hex(packet.payload))) | ||||
| 
 | ||||
|     def close(self) -> None: | ||||
|         self.executor_service.shutdown() | ||||
| 
 | ||||
|     class Channel: | ||||
|         channel_manager: ChannelManager | ||||
|         chunk_id: int | ||||
|         q = queue.Queue() | ||||
|         __buffer: io.BytesIO | ||||
|         __chunk_index: int | ||||
|         __file: AudioFile | ||||
|         __header: bool = True | ||||
| 
 | ||||
|         def __init__(self, channel_manager: ChannelManager, file: AudioFile, | ||||
|                      chunk_index: int): | ||||
|             self.__buffer = io.BytesIO() | ||||
|             self.channel_manager = channel_manager | ||||
|             self.__file = file | ||||
|             self.__chunk_index = chunk_index | ||||
|             with self.channel_manager.seq_holder_lock: | ||||
|                 self.chunk_id = self.channel_manager.seq_holder | ||||
|                 self.channel_manager.seq_holder += 1 | ||||
|             self.channel_manager.executor_service.submit( | ||||
|                 lambda: ChannelManager.Channel.Handler(self)) | ||||
| 
 | ||||
|         def _handle(self, payload: bytes) -> bool: | ||||
|             if len(payload) == 0: | ||||
|                 if not self.__header: | ||||
|                     self.__file.write_chunk(payload, self.__chunk_index, False) | ||||
|                     return True | ||||
|                 self.channel_manager.logger.debug( | ||||
|                     "Received empty chunk, skipping.") | ||||
|                 return False | ||||
|             if self.__header: | ||||
|                 length: int | ||||
|                 while len(payload.buffer) > 0: | ||||
|                     length = payload.read_short() | ||||
|                     if not length > 0: | ||||
|                         break | ||||
|                     header_id = payload.read_byte() | ||||
|                     header_data = payload.read(length - 1) | ||||
|                     self.__file.write_header(int.from_bytes(header_id, "big"), | ||||
|                                              bytearray(header_data), False) | ||||
|                 self.__header = False | ||||
|             else: | ||||
|                 self.__buffer.write(payload.read(len(payload.buffer))) | ||||
|             return False | ||||
| 
 | ||||
|         def add_to_queue(self, payload): | ||||
|             self.q.put(payload) | ||||
| 
 | ||||
|         def stream_error(self, code: int) -> None: | ||||
|             self.__file.stream_error(self.__chunk_index, code) | ||||
| 
 | ||||
|         class Handler: | ||||
|             __channel: ChannelManager.Channel = None | ||||
| 
 | ||||
|             def __init__(self, channel: ChannelManager.Channel): | ||||
|                 self.__channel = channel | ||||
| 
 | ||||
|             def run(self) -> None: | ||||
|                 self.__channel.channel_manager.logger.debug( | ||||
|                     "ChannelManager.Handler is starting") | ||||
|                 with self.__channel.q.all_tasks_done: | ||||
|                     self.__channel.channel_manager.channels.pop( | ||||
|                         self.__channel.chunk_id) | ||||
|                 self.__channel.channel_manager.logger.debug( | ||||
|                     "ChannelManager.Handler is shutting down") | ||||
							
								
								
									
										18
									
								
								resources/lib/librespot/cache.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								resources/lib/librespot/cache.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,18 @@ | |||
| from __future__ import annotations | ||||
| import typing | ||||
| 
 | ||||
| if typing.TYPE_CHECKING: | ||||
|     from librespot.core import Session | ||||
| 
 | ||||
| 
 | ||||
| class CacheManager: | ||||
|     clean_up_threshold = 604800000 | ||||
|     header_hash = 253 | ||||
|     header_timestamp = 254 | ||||
|     parent: str | ||||
| 
 | ||||
|     def __init__(self, session: Session): | ||||
|         """ | ||||
|         @Todo Implement function | ||||
|         :param session: | ||||
|         """ | ||||
							
								
								
									
										2307
									
								
								resources/lib/librespot/core.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										2307
									
								
								resources/lib/librespot/core.py
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										412
									
								
								resources/lib/librespot/crypto.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										412
									
								
								resources/lib/librespot/crypto.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,412 @@ | |||
| from __future__ import annotations | ||||
| from Cryptodome import Random | ||||
| from librespot import util | ||||
| import io | ||||
| import re | ||||
| import struct | ||||
| import typing | ||||
| 
 | ||||
| if typing.TYPE_CHECKING: | ||||
|     from librespot.core import Session | ||||
| 
 | ||||
| 
 | ||||
| class CipherPair: | ||||
|     __receive_cipher: Shannon | ||||
|     __receive_nonce = 0 | ||||
|     __send_cipher: Shannon | ||||
|     __send_nonce = 0 | ||||
| 
 | ||||
|     def __init__(self, send_key: bytes, receive_key: bytes): | ||||
|         self.__send_cipher = Shannon() | ||||
|         self.__send_cipher.key(send_key) | ||||
|         self.__receive_cipher = Shannon() | ||||
|         self.__receive_cipher.key(receive_key) | ||||
| 
 | ||||
|     def send_encoded(self, connection: Session.ConnectionHolder, cmd: bytes, | ||||
|                      payload: bytes) -> None: | ||||
|         """ | ||||
|         Send decrypted data to the socket | ||||
|         :param connection: | ||||
|         :param cmd: | ||||
|         :param payload: | ||||
|         :return: | ||||
|         """ | ||||
|         self.__send_cipher.nonce(self.__send_nonce) | ||||
|         self.__send_nonce += 1 | ||||
|         buffer = io.BytesIO() | ||||
|         buffer.write(cmd) | ||||
|         buffer.write(struct.pack(">H", len(payload))) | ||||
|         buffer.write(payload) | ||||
|         buffer.seek(0) | ||||
|         contents = self.__send_cipher.encrypt(buffer.read()) | ||||
|         mac = self.__send_cipher.finish(4) | ||||
|         connection.write(contents) | ||||
|         connection.write(mac) | ||||
|         connection.flush() | ||||
| 
 | ||||
|     def receive_encoded(self, connection: Session.ConnectionHolder) -> Packet: | ||||
|         """ | ||||
|         Receive and parse decrypted data from the socket | ||||
|         Args: | ||||
|             connection: ConnectionHolder | ||||
|         Return: | ||||
|             The parsed packet will be returned | ||||
|         """ | ||||
|         try: | ||||
|             self.__receive_cipher.nonce(self.__receive_nonce) | ||||
|             self.__receive_nonce += 1 | ||||
|             header_bytes = self.__receive_cipher.decrypt(connection.read(3)) | ||||
|             cmd = struct.pack(">s", bytes([header_bytes[0]])) | ||||
|             payload_length = (header_bytes[1] << 8) | (header_bytes[2] & 0xff) | ||||
|             payload_bytes = self.__receive_cipher.decrypt( | ||||
|                 connection.read(payload_length)) | ||||
|             mac = connection.read(4) | ||||
|             expected_mac = self.__receive_cipher.finish(4) | ||||
|             if mac != expected_mac: | ||||
|                 raise RuntimeError() | ||||
|             return Packet(cmd, payload_bytes) | ||||
|         except IndexError: | ||||
|             raise RuntimeError("Failed to receive packet") | ||||
| 
 | ||||
| 
 | ||||
| class DiffieHellman: | ||||
|     """ | ||||
|     DiffieHellman Keyexchange | ||||
|     """ | ||||
|     __prime = int.from_bytes( | ||||
|         b'\xff\xff\xff\xff\xff\xff\xff\xff\xc9\x0f' | ||||
|         b'\xda\xa2!h\xc24\xc4\xc6b\x8b\x80\xdc\x1c' | ||||
|         b'\xd1)\x02N\x08\x8ag\xcct\x02\x0b\xbe\xa6;' | ||||
|         b'\x13\x9b"QJ\x08y\x8e4\x04\xdd\xef\x95\x19' | ||||
|         b'\xb3\xcd:C\x1b0+\nm\xf2_\x147O\xe15mmQ\xc2' | ||||
|         b'E\xe4\x85\xb5vb^~\xc6\xf4LB\xe9\xa6:6 \xff' | ||||
|         b'\xff\xff\xff\xff\xff\xff\xff', | ||||
|         byteorder="big") | ||||
|     __private_key: int | ||||
|     __public_key: int | ||||
| 
 | ||||
|     def __init__(self): | ||||
|         key_data = Random.get_random_bytes(0x5f) | ||||
|         self.__private_key = int.from_bytes(key_data, byteorder="big") | ||||
|         self.__public_key = pow(2, self.__private_key, self.__prime) | ||||
| 
 | ||||
|     def compute_shared_key(self, remote_key_bytes: bytes): | ||||
|         """ | ||||
|         Compute shared_key | ||||
|         """ | ||||
|         remote_key = int.from_bytes(remote_key_bytes, "big") | ||||
|         return pow(remote_key, self.__private_key, self.__prime) | ||||
| 
 | ||||
|     def private_key(self) -> int: | ||||
|         """ | ||||
|         Return DiffieHellman's private key | ||||
|         Returns: | ||||
|             DiffieHellman's private key | ||||
|         """ | ||||
|         return self.__private_key | ||||
| 
 | ||||
|     def public_key(self) -> int: | ||||
|         """ | ||||
|         Return DiffieHellman's public key | ||||
|         Returns: | ||||
|             DiffieHellman's public key | ||||
|         """ | ||||
|         return self.__public_key | ||||
| 
 | ||||
|     def public_key_bytes(self) -> bytes: | ||||
|         """ | ||||
|         Return DiffieHellman's packed public key | ||||
|         Returns: | ||||
|             DiffieHellman's packed public key | ||||
|         """ | ||||
|         return util.int_to_bytes(self.__public_key) | ||||
| 
 | ||||
| 
 | ||||
| class Packet: | ||||
|     cmd: bytes | ||||
|     payload: bytes | ||||
| 
 | ||||
|     def __init__(self, cmd: bytes, payload: bytes): | ||||
|         self.cmd = cmd | ||||
|         self.payload = payload | ||||
| 
 | ||||
|     def is_cmd(self, cmd: bytes) -> bool: | ||||
|         return cmd == self.cmd | ||||
| 
 | ||||
|     class Type: | ||||
|         secret_block = b"\x02" | ||||
|         ping = b"\x04" | ||||
|         stream_chunk = b"\x08" | ||||
|         stream_chunk_res = b"\x09" | ||||
|         channel_error = b"\x0a" | ||||
|         channel_abort = b"\x0b" | ||||
|         request_key = b"\x0c" | ||||
|         aes_key = b"\x0d" | ||||
|         aes_key_error = b"\x0e" | ||||
|         image = b"\x19" | ||||
|         country_code = b"\x1b" | ||||
|         pong = b"\x49" | ||||
|         pong_ack = b"\x4a" | ||||
|         pause = b"\x4b" | ||||
|         product_info = b"\x50" | ||||
|         legacy_welcome = b"\x69" | ||||
|         license_version = b"\x76" | ||||
|         login = b"\xab" | ||||
|         ap_welcome = b"\xac" | ||||
|         auth_failure = b"\xad" | ||||
|         mercury_req = b"\xb2" | ||||
|         mercury_sub = b"\xb3" | ||||
|         mercury_unsub = b"\xb4" | ||||
|         mercury_event = b"\xb5" | ||||
|         track_ended_time = b"\x82" | ||||
|         unknown_data_all_zeros = b"\x1f" | ||||
|         preferred_locale = b"\x74" | ||||
|         unknown_0x4f = b"\x4f" | ||||
|         unknown_0x0f = b"\x0f" | ||||
|         unknown_0x10 = b"\x10" | ||||
| 
 | ||||
|         @staticmethod | ||||
|         def parse(val: typing.Union[bytes, None]) -> typing.Union[bytes, None]: | ||||
|             for cmd in [ | ||||
|                     Packet.Type.__dict__[attr] for attr in Packet.Type.__dict__ | ||||
|                     if re.search("__.+?__", attr) is None | ||||
|                     and type(Packet.Type.__dict__[attr]) is bytes | ||||
|             ]: | ||||
|                 if cmd == val: | ||||
|                     return cmd | ||||
|             return None | ||||
| 
 | ||||
|         @staticmethod | ||||
|         def for_method(method: str) -> bytes: | ||||
|             if method == "SUB": | ||||
|                 return Packet.Type.mercury_sub | ||||
|             if method == "UNSUB": | ||||
|                 return Packet.Type.mercury_unsub | ||||
|             return Packet.Type.mercury_req | ||||
| 
 | ||||
| 
 | ||||
| class Shannon: | ||||
|     n = 16 | ||||
|     fold = n | ||||
|     initkonst = 0x6996c53a | ||||
|     keyp = 13 | ||||
|     r: list | ||||
|     crc: list | ||||
|     init_r: list | ||||
|     konst: int | ||||
|     sbuf: int | ||||
|     mbuf: int | ||||
|     nbuf: int | ||||
| 
 | ||||
|     def __init__(self): | ||||
|         self.r = [0 for _ in range(self.n)] | ||||
|         self.crc = [0 for _ in range(self.n)] | ||||
|         self.init_r = [0 for _ in range(self.n)] | ||||
| 
 | ||||
|     def rotl(self, i: int, distance: int) -> int: | ||||
|         return ((i << distance) | (i >> (32 - distance))) & 0xffffffff | ||||
| 
 | ||||
|     def sbox(self, i: int) -> int: | ||||
|         i ^= self.rotl(i, 5) | self.rotl(i, 7) | ||||
|         i ^= self.rotl(i, 19) | self.rotl(i, 22) | ||||
|         return i | ||||
| 
 | ||||
|     def sbox2(self, i: int) -> int: | ||||
|         i ^= self.rotl(i, 7) | self.rotl(i, 22) | ||||
|         i ^= self.rotl(i, 5) | self.rotl(i, 19) | ||||
|         return i | ||||
| 
 | ||||
|     def cycle(self) -> None: | ||||
|         t: int | ||||
|         t = self.r[12] ^ self.r[13] ^ self.konst | ||||
|         t = self.sbox(t) ^ self.rotl(self.r[0], 1) | ||||
|         for i in range(1, self.n): | ||||
|             self.r[i - 1] = self.r[i] | ||||
|         self.r[self.n - 1] = t | ||||
|         t = self.sbox2(self.r[2] ^ self.r[15]) | ||||
|         self.r[0] ^= t | ||||
|         self.sbuf = t ^ self.r[8] ^ self.r[12] | ||||
| 
 | ||||
|     def crc_func(self, i: int) -> None: | ||||
|         t: int | ||||
|         t = self.crc[0] ^ self.crc[2] ^ self.crc[15] ^ i | ||||
|         for j in range(1, self.n): | ||||
|             self.crc[j - 1] = self.crc[j] | ||||
|         self.crc[self.n - 1] = t | ||||
| 
 | ||||
|     def mac_func(self, i: int) -> None: | ||||
|         self.crc_func(i) | ||||
|         self.r[self.keyp] ^= i | ||||
| 
 | ||||
|     def init_state(self) -> None: | ||||
|         self.r[0] = 1 | ||||
|         self.r[1] = 1 | ||||
|         for i in range(2, self.n): | ||||
|             self.r[i] = self.r[i - 1] + self.r[i - 2] | ||||
|         self.konst = self.initkonst | ||||
| 
 | ||||
|     def save_state(self) -> None: | ||||
|         for i in range(self.n): | ||||
|             self.init_r[i] = self.r[i] | ||||
| 
 | ||||
|     def reload_state(self) -> None: | ||||
|         for i in range(self.n): | ||||
|             self.r[i] = self.init_r[i] | ||||
| 
 | ||||
|     def gen_konst(self) -> None: | ||||
|         self.konst = self.r[0] | ||||
| 
 | ||||
|     def add_key(self, k: int) -> None: | ||||
|         self.r[self.keyp] ^= k | ||||
| 
 | ||||
|     def diffuse(self) -> None: | ||||
|         for _ in range(self.fold): | ||||
|             self.cycle() | ||||
| 
 | ||||
|     def load_key(self, key: bytes) -> None: | ||||
|         i: int | ||||
|         j: int | ||||
|         t: int | ||||
|         padding_size = int((len(key) + 3) / 4) * 4 - len(key) | ||||
|         key = key + (b"\x00" * padding_size) + struct.pack("<I", len(key)) | ||||
|         for i in range(0, len(key), 4): | ||||
|             self.r[self.keyp] = \ | ||||
|                 self.r[self.keyp] ^ \ | ||||
|                 struct.unpack("<I", key[i: i + 4])[0] | ||||
|             self.cycle() | ||||
|         for i in range(self.n): | ||||
|             self.crc[i] = self.r[i] | ||||
|         self.diffuse() | ||||
|         for i in range(self.n): | ||||
|             self.r[i] ^= self.crc[i] | ||||
| 
 | ||||
|     def key(self, key: bytes) -> None: | ||||
|         self.init_state() | ||||
|         self.load_key(key) | ||||
|         self.gen_konst() | ||||
|         self.save_state() | ||||
|         self.nbuf = 0 | ||||
| 
 | ||||
|     def nonce(self, nonce: typing.Union[bytes, int]) -> None: | ||||
|         if type(nonce) is int: | ||||
|             nonce = bytes(struct.pack(">I", nonce)) | ||||
|         self.reload_state() | ||||
|         self.konst = self.initkonst | ||||
|         self.load_key(nonce) | ||||
|         self.gen_konst() | ||||
|         self.nbuf = 0 | ||||
| 
 | ||||
|     def encrypt(self, buffer: bytes, n: int = None) -> bytes: | ||||
|         if n is None: | ||||
|             return self.encrypt(buffer, len(buffer)) | ||||
|         buffer = bytearray(buffer) | ||||
|         i = 0 | ||||
|         j: int | ||||
|         t: int | ||||
|         if self.nbuf != 0: | ||||
|             while self.nbuf != 0 and n != 0: | ||||
|                 self.mbuf ^= (buffer[i] & 0xff) << (32 - self.nbuf) | ||||
|                 buffer[i] ^= (self.sbuf >> (32 - self.nbuf)) & 0xff | ||||
|                 i += 1 | ||||
|                 self.nbuf -= 8 | ||||
|                 n -= 1 | ||||
|             if self.nbuf != 0: | ||||
|                 return b"" | ||||
|             self.mac_func(self.mbuf) | ||||
|         j = n & ~0x03 | ||||
|         while i < j: | ||||
|             self.cycle() | ||||
|             t = ((buffer[i + 3] & 0xFF) << 24) | \ | ||||
|                 ((buffer[i + 2] & 0xFF) << 16) | \ | ||||
|                 ((buffer[i + 1] & 0xFF) << 8) | \ | ||||
|                 (buffer[i] & 0xFF) | ||||
|             self.mac_func(t) | ||||
|             t ^= self.sbuf | ||||
|             buffer[i + 3] = (t >> 24) & 0xFF | ||||
|             buffer[i + 2] = (t >> 16) & 0xFF | ||||
|             buffer[i + 1] = (t >> 8) & 0xFF | ||||
|             buffer[i] = t & 0xFF | ||||
|             i += 4 | ||||
|         n &= 0x03 | ||||
|         if n != 0: | ||||
|             self.cycle() | ||||
|             self.mbuf = 0 | ||||
|             self.nbuf = 32 | ||||
|             while self.nbuf != 0 and n != 0: | ||||
|                 self.mbuf ^= (buffer[i] & 0xff) << (32 - self.nbuf) | ||||
|                 buffer[i] ^= (self.sbuf >> (32 - self.nbuf)) & 0xff | ||||
|                 i += 1 | ||||
|                 self.nbuf -= 8 | ||||
|                 n -= 1 | ||||
|         return bytes(buffer) | ||||
| 
 | ||||
|     def decrypt(self, buffer: bytes, n: int = None) -> bytes: | ||||
|         if n is None: | ||||
|             return self.decrypt(buffer, len(buffer)) | ||||
|         buffer = bytearray(buffer) | ||||
|         i = 0 | ||||
|         j: int | ||||
|         t: int | ||||
|         if self.nbuf != 0: | ||||
|             while self.nbuf != 0 and n != 0: | ||||
|                 buffer[i] ^= (self.sbuf >> (32 - self.nbuf)) & 0xff | ||||
|                 self.mbuf ^= (buffer[i] & 0xff) << (32 - self.nbuf) | ||||
|                 i += 1 | ||||
|                 self.nbuf -= 8 | ||||
|                 n -= 1 | ||||
|             if self.nbuf != 0: | ||||
|                 return b"" | ||||
|             self.mac_func(self.mbuf) | ||||
|         j = n & ~0x03 | ||||
|         while i < j: | ||||
|             self.cycle() | ||||
|             t = ((buffer[i + 3] & 0xFF) << 24) | \ | ||||
|                 ((buffer[i + 2] & 0xFF) << 16) | \ | ||||
|                 ((buffer[i + 1] & 0xFF) << 8) | \ | ||||
|                 (buffer[i] & 0xFF) | ||||
|             t ^= self.sbuf | ||||
|             self.mac_func(t) | ||||
|             buffer[i + 3] = (t >> 24) & 0xFF | ||||
|             buffer[i + 2] = (t >> 16) & 0xFF | ||||
|             buffer[i + 1] = (t >> 8) & 0xFF | ||||
|             buffer[i] = t & 0xFF | ||||
|             i += 4 | ||||
|         n &= 0x03 | ||||
|         if n != 0: | ||||
|             self.cycle() | ||||
|             self.mbuf = 0 | ||||
|             self.nbuf = 32 | ||||
|             while self.nbuf != 0 and n != 0: | ||||
|                 buffer[i] ^= (self.sbuf >> (32 - self.nbuf)) & 0xff | ||||
|                 self.mbuf ^= (buffer[i] & 0xff) << (32 - self.nbuf) | ||||
|                 i += 1 | ||||
|                 self.nbuf -= 8 | ||||
|                 n -= 1 | ||||
|         return bytes(buffer) | ||||
| 
 | ||||
|     def finish(self, n: int) -> bytes: | ||||
|         buffer = bytearray(4) | ||||
|         i = 0 | ||||
|         j: int | ||||
|         if self.nbuf != 0: | ||||
|             self.mac_func(self.mbuf) | ||||
|         self.cycle() | ||||
|         self.add_key(self.initkonst ^ (self.nbuf << 3)) | ||||
|         self.nbuf = 0 | ||||
|         for j in range(self.n): | ||||
|             self.r[j] ^= self.crc[j] | ||||
|         self.diffuse() | ||||
|         while n > 0: | ||||
|             self.cycle() | ||||
|             if n >= 4: | ||||
|                 buffer[i + 3] = (self.sbuf >> 24) & 0xff | ||||
|                 buffer[i + 2] = (self.sbuf >> 16) & 0xff | ||||
|                 buffer[i + 1] = (self.sbuf >> 8) & 0xff | ||||
|                 buffer[i] = self.sbuf & 0xff | ||||
|                 n -= 4 | ||||
|                 i += 4 | ||||
|             else: | ||||
|                 for j in range(n): | ||||
|                     buffer[i + j] = (self.sbuf >> (i * 8)) & 0xff | ||||
|                 break | ||||
|         return bytes(buffer) | ||||
							
								
								
									
										11
									
								
								resources/lib/librespot/dealer.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								resources/lib/librespot/dealer.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,11 @@ | |||
| from __future__ import annotations | ||||
| from librespot.core import ApResolver | ||||
| from librespot.metadata import AlbumId, ArtistId, EpisodeId, ShowId, TrackId | ||||
| from librespot.proto import Connect_pb2 as Connect, Metadata_pb2 as Metadata | ||||
| from librespot.structure import Closeable | ||||
| import logging | ||||
| import requests | ||||
| import typing | ||||
| 
 | ||||
| if typing.TYPE_CHECKING: | ||||
|     from librespot.core import Session | ||||
							
								
								
									
										394
									
								
								resources/lib/librespot/mercury.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										394
									
								
								resources/lib/librespot/mercury.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,394 @@ | |||
| from __future__ import annotations | ||||
| from librespot import util | ||||
| from librespot.crypto import Packet | ||||
| from librespot.proto import Mercury_pb2 as Mercury, Pubsub_pb2 as Pubsub | ||||
| from librespot.structure import Closeable, PacketsReceiver, SubListener | ||||
| import io | ||||
| import json | ||||
| import logging | ||||
| import queue | ||||
| import struct | ||||
| import threading | ||||
| import typing | ||||
| 
 | ||||
| if typing.TYPE_CHECKING: | ||||
|     from librespot.core import Session | ||||
| 
 | ||||
| 
 | ||||
| class JsonMercuryRequest: | ||||
|     request: RawMercuryRequest | ||||
| 
 | ||||
|     def __init__(self, request: RawMercuryRequest): | ||||
|         self.request = request | ||||
| 
 | ||||
| 
 | ||||
| class MercuryClient(Closeable, PacketsReceiver): | ||||
|     logger = logging.getLogger("Librespot:MercuryClient") | ||||
|     mercury_request_timeout = 3 | ||||
|     __callbacks: typing.Dict[int, Callback] = {} | ||||
|     __remove_callback_lock = threading.Condition() | ||||
|     __partials: typing.Dict[int, typing.List[bytes]] = {} | ||||
|     __seq_holder = 0 | ||||
|     __seq_holder_lock = threading.Condition() | ||||
|     __session: Session | ||||
|     __subscriptions: typing.List[InternalSubListener] = [] | ||||
|     __subscriptions_lock = threading.Condition() | ||||
| 
 | ||||
|     def __init__(self, session: Session): | ||||
|         self.__session = session | ||||
| 
 | ||||
|     def close(self) -> None: | ||||
|         """ | ||||
|         Close the MercuryClient instance | ||||
|         """ | ||||
|         if len(self.__subscriptions) != 0: | ||||
|             for listener in self.__subscriptions: | ||||
|                 if listener.is_sub: | ||||
|                     self.unsubscribe(listener.uri) | ||||
|                 else: | ||||
|                     self.not_interested_in(listener.listener) | ||||
|         if len(self.__callbacks) != 0: | ||||
|             with self.__remove_callback_lock: | ||||
|                 self.__remove_callback_lock.wait(self.mercury_request_timeout) | ||||
|         self.__callbacks.clear() | ||||
| 
 | ||||
|     def dispatch(self, packet: Packet) -> None: | ||||
|         payload = io.BytesIO(packet.payload) | ||||
|         seq_length = struct.unpack(">H", payload.read(2))[0] | ||||
|         if seq_length == 2: | ||||
|             seq = struct.unpack(">H", payload.read(2))[0] | ||||
|         elif seq_length == 4: | ||||
|             seq = struct.unpack(">i", payload.read(4))[0] | ||||
|         elif seq_length == 8: | ||||
|             seq = struct.unpack(">q", payload.read(8))[0] | ||||
|         else: | ||||
|             raise RuntimeError("Unknown seq length: {}".format(seq_length)) | ||||
|         flags = payload.read(1) | ||||
|         parts = struct.unpack(">H", payload.read(2))[0] | ||||
|         partial = self.__partials.get(seq) | ||||
|         if partial is None or flags == 0: | ||||
|             partial = [] | ||||
|             self.__partials[seq] = partial | ||||
|         self.logger.debug( | ||||
|             "Handling packet, cmd: 0x{}, seq: {}, flags: {}, parts: {}".format( | ||||
|                 util.bytes_to_hex(packet.cmd), seq, flags, parts)) | ||||
|         for _ in range(parts): | ||||
|             size = struct.unpack(">H", payload.read(2))[0] | ||||
|             buffer = payload.read(size) | ||||
|             partial.append(buffer) | ||||
|             self.__partials[seq] = partial | ||||
|         if flags != b"\x01": | ||||
|             return | ||||
|         self.__partials.pop(seq) | ||||
|         header = Mercury.Header() | ||||
|         header.ParseFromString(partial[0]) | ||||
|         response = MercuryClient.Response(header, partial) | ||||
|         if packet.is_cmd(Packet.Type.mercury_event): | ||||
|             dispatched = False | ||||
|             with self.__subscriptions_lock: | ||||
|                 for sub in self.__subscriptions: | ||||
|                     if sub.matches(header.uri): | ||||
|                         sub.dispatch(response) | ||||
|                         dispatched = True | ||||
|             if not dispatched: | ||||
|                 self.logger.debug( | ||||
|                     "Couldn't dispatch Mercury event seq: {}, uri: {}, code: {}, payload: {}" | ||||
|                     .format(seq, header.uri, header.status_code, | ||||
|                             response.payload)) | ||||
|         elif (packet.is_cmd(Packet.Type.mercury_req) | ||||
|               or packet.is_cmd(Packet.Type.mercury_sub) | ||||
|               or packet.is_cmd(Packet.Type.mercury_sub)): | ||||
|             callback = self.__callbacks.get(seq) | ||||
|             self.__callbacks.pop(seq) | ||||
|             if callback is not None: | ||||
|                 callback.response(response) | ||||
|             else: | ||||
|                 self.logger.warning( | ||||
|                     "Skipped Mercury response, seq: {}, uri: {}, code: {}". | ||||
|                     format(seq, response.uri, response.status_code)) | ||||
|             with self.__remove_callback_lock: | ||||
|                 self.__remove_callback_lock.notify_all() | ||||
|         else: | ||||
|             self.logger.warning( | ||||
|                 "Couldn't handle packet, seq: {}, uri: {}, code: {}".format( | ||||
|                     seq, header.uri, header.status_code)) | ||||
| 
 | ||||
|     def interested_in(self, uri: str, listener: SubListener) -> None: | ||||
|         self.__subscriptions.append( | ||||
|             MercuryClient.InternalSubListener(uri, listener, False)) | ||||
| 
 | ||||
|     def not_interested_in(self, listener: SubListener) -> None: | ||||
|         try: | ||||
|             for subscription in self.__subscriptions: | ||||
|                 if subscription.listener is listener: | ||||
|                     self.__subscriptions.remove(subscription) | ||||
|                     break | ||||
|         except ValueError: | ||||
|             pass | ||||
| 
 | ||||
|     def send(self, request: RawMercuryRequest, callback) -> int: | ||||
|         """ | ||||
|         Send the Mercury request | ||||
|         Args: | ||||
|             request: RawMercuryRequest | ||||
|             callback: Callback function | ||||
|         Returns: | ||||
|             MercuryClient.Response | ||||
|         """ | ||||
|         buffer = io.BytesIO() | ||||
|         seq: int | ||||
|         with self.__seq_holder_lock: | ||||
|             seq = self.__seq_holder | ||||
|             self.__seq_holder += 1 | ||||
|         self.logger.debug( | ||||
|             "Send Mercury request, seq: {}, uri: {}, method: {}".format( | ||||
|                 seq, request.header.uri, request.header.method)) | ||||
|         buffer.write(struct.pack(">H", 4)) | ||||
|         buffer.write(struct.pack(">i", seq)) | ||||
|         buffer.write(b"\x01") | ||||
|         buffer.write(struct.pack(">H", 1 + len(request.payload))) | ||||
|         header_bytes = request.header.SerializeToString() | ||||
|         buffer.write(struct.pack(">H", len(header_bytes))) | ||||
|         buffer.write(header_bytes) | ||||
|         for part in request.payload: | ||||
|             buffer.write(struct.pack(">H", len(part))) | ||||
|             buffer.write(part) | ||||
|         buffer.seek(0) | ||||
|         cmd = Packet.Type.for_method(request.header.method) | ||||
|         self.__session.send(cmd, buffer.read()) | ||||
|         self.__callbacks[seq] = callback | ||||
|         return seq | ||||
| 
 | ||||
|     def send_sync(self, request: RawMercuryRequest) -> Response: | ||||
|         """ | ||||
|         Send the Mercury request | ||||
|         Args: | ||||
|             request: RawMercuryRequest | ||||
|         Returns: | ||||
|             MercuryClient.Response | ||||
|         """ | ||||
|         callback = MercuryClient.SyncCallback() | ||||
|         seq = self.send(request, callback) | ||||
|         try: | ||||
|             response = callback.wait_response() | ||||
|             if response is None: | ||||
|                 raise IOError( | ||||
|                     "Request timeout out, {} passed, yet no response. seq: {}". | ||||
|                     format(self.mercury_request_timeout, seq)) | ||||
|             return response | ||||
|         except queue.Empty as e: | ||||
|             raise IOError(e) | ||||
| 
 | ||||
|     def send_sync_json(self, request: JsonMercuryRequest) -> typing.Any: | ||||
|         response = self.send_sync(request.request) | ||||
|         if 200 <= response.status_code < 300: | ||||
|             return json.loads(response.payload) | ||||
|         raise MercuryClient.MercuryException(response) | ||||
| 
 | ||||
|     def subscribe(self, uri: str, listener: SubListener) -> None: | ||||
|         """ | ||||
|         Subscribe URI | ||||
|         Args: | ||||
|             uri: | ||||
|             listener: | ||||
|         """ | ||||
|         response = self.send_sync(RawMercuryRequest.sub(uri)) | ||||
|         if response.status_code != 200: | ||||
|             raise RuntimeError(response) | ||||
|         if len(response.payload) > 0: | ||||
|             for payload in response.payload: | ||||
|                 sub = Pubsub.Subscription() | ||||
|                 sub.ParseFromString(payload) | ||||
|                 self.__subscriptions.append( | ||||
|                     MercuryClient.InternalSubListener(sub.uri, listener, True)) | ||||
|         else: | ||||
|             self.__subscriptions.append( | ||||
|                 MercuryClient.InternalSubListener(uri, listener, True)) | ||||
|         self.logger.debug("Subscribed successfully to {}!".format(uri)) | ||||
| 
 | ||||
|     def unsubscribe(self, uri) -> None: | ||||
|         """ | ||||
|         Unsubscribe URI | ||||
|         Args: | ||||
|             uri: | ||||
|         """ | ||||
|         response = self.send_sync(RawMercuryRequest.unsub(uri)) | ||||
|         if response.status_code != 200: | ||||
|             raise RuntimeError(response) | ||||
|         for subscription in self.__subscriptions: | ||||
|             if subscription.matches(uri): | ||||
|                 self.__subscriptions.remove(subscription) | ||||
|                 break | ||||
|         self.logger.debug("Unsubscribed successfully from {}!".format(uri)) | ||||
| 
 | ||||
|     class Callback: | ||||
|         def response(self, response: MercuryClient.Response) -> None: | ||||
|             raise NotImplementedError | ||||
| 
 | ||||
|     class InternalSubListener: | ||||
|         uri: str | ||||
|         listener: SubListener | ||||
|         is_sub: bool | ||||
| 
 | ||||
|         def __init__(self, uri: str, listener: SubListener, is_sub: bool): | ||||
|             self.uri = uri | ||||
|             self.listener = listener | ||||
|             self.is_sub = is_sub | ||||
| 
 | ||||
|         def matches(self, uri: str) -> bool: | ||||
|             """ | ||||
|             Compare with the URI given | ||||
|             Args: | ||||
|                 uri: URI to be compared | ||||
|             Returns: | ||||
|                 bool | ||||
|             """ | ||||
|             return uri.startswith(self.uri) | ||||
| 
 | ||||
|         def dispatch(self, response: MercuryClient.Response) -> None: | ||||
|             """ | ||||
|             Dispatch the event response | ||||
|             Args: | ||||
|                 response: Response generated by the event | ||||
|             """ | ||||
|             self.listener.event(response) | ||||
| 
 | ||||
|     class MercuryException(Exception): | ||||
|         code: int | ||||
| 
 | ||||
|         def __init__(self, response: MercuryClient.Response): | ||||
|             super().__init__("status: {}".format(response.status_code)) | ||||
|             self.code = response.status_code | ||||
| 
 | ||||
|     class PubSubException(MercuryException): | ||||
|         pass | ||||
| 
 | ||||
|     class Response: | ||||
|         uri: str | ||||
|         payload: bytes | ||||
|         status_code: int | ||||
| 
 | ||||
|         def __init__(self, header: Mercury.Header, payload: list[bytes]): | ||||
|             self.uri = header.uri | ||||
|             self.status_code = header.status_code | ||||
|             self.payload = b"".join(payload[1:]) | ||||
| 
 | ||||
|     class SyncCallback(Callback): | ||||
|         __reference = queue.Queue() | ||||
| 
 | ||||
|         def response(self, response: MercuryClient.Response) -> None: | ||||
|             """ | ||||
|             Set the response | ||||
|             :param response: | ||||
|             :return: | ||||
|             """ | ||||
|             self.__reference.put(response) | ||||
|             self.__reference.task_done() | ||||
| 
 | ||||
|         def wait_response(self) -> typing.Any: | ||||
|             return self.__reference.get( | ||||
|                 timeout=MercuryClient.mercury_request_timeout) | ||||
| 
 | ||||
| 
 | ||||
| class MercuryRequests: | ||||
|     keymaster_client_id = "65b708073fc0480ea92a077233ca87bd" | ||||
| 
 | ||||
|     @staticmethod | ||||
|     def get_root_playlists(username: str): | ||||
|         """ | ||||
|         @TODO implement function | ||||
|         """ | ||||
| 
 | ||||
|     @staticmethod | ||||
|     def request_token(device_id, scope): | ||||
|         return JsonMercuryRequest( | ||||
|             RawMercuryRequest.get( | ||||
|                 "hm://keymaster/token/authenticated?scope={}&client_id={}&device_id={}" | ||||
|                 .format(scope, MercuryRequests.keymaster_client_id, | ||||
|                         device_id))) | ||||
| 
 | ||||
| 
 | ||||
| class RawMercuryRequest: | ||||
|     header: Mercury.Header | ||||
|     payload: typing.List[bytes] | ||||
| 
 | ||||
|     def __init__(self, header: Mercury.Header, payload: typing.List[bytes]): | ||||
|         self.header = header | ||||
|         self.payload = payload | ||||
| 
 | ||||
|     @staticmethod | ||||
|     def sub(uri: str): | ||||
|         return RawMercuryRequest.new_builder().set_uri(uri).set_method( | ||||
|             "SUB").build() | ||||
| 
 | ||||
|     @staticmethod | ||||
|     def unsub(uri: str): | ||||
|         return RawMercuryRequest.new_builder().set_uri(uri).set_method( | ||||
|             "UNSUB").build() | ||||
| 
 | ||||
|     @staticmethod | ||||
|     def get(uri: str): | ||||
|         return RawMercuryRequest.new_builder().set_uri(uri).set_method( | ||||
|             "GET").build() | ||||
| 
 | ||||
|     @staticmethod | ||||
|     def send(uri: str, part: bytes): | ||||
|         return RawMercuryRequest.new_builder().set_uri(uri) \ | ||||
|             .add_payload_part(part).set_method("SEND").build() | ||||
| 
 | ||||
|     @staticmethod | ||||
|     def post(uri: str, part: bytes): | ||||
|         return RawMercuryRequest.new_builder().set_uri(uri) \ | ||||
|             .set_method("POST").add_payload_part(part).build() | ||||
| 
 | ||||
|     @staticmethod | ||||
|     def new_builder(): | ||||
|         return RawMercuryRequest.Builder() | ||||
| 
 | ||||
|     class Builder: | ||||
|         header_dict: dict | ||||
|         payload: typing.List[bytes] | ||||
| 
 | ||||
|         def __init__(self): | ||||
|             self.header_dict = {} | ||||
|             self.payload = [] | ||||
| 
 | ||||
|         def set_uri(self, uri: str): | ||||
|             self.header_dict["uri"] = uri | ||||
|             return self | ||||
| 
 | ||||
|         def set_content_type(self, content_type: str): | ||||
|             self.header_dict["content_type"] = content_type | ||||
|             return self | ||||
| 
 | ||||
|         def set_method(self, method: str): | ||||
|             self.header_dict["method"] = method | ||||
|             return self | ||||
| 
 | ||||
|         def add_user_field(self, | ||||
|                            field: Mercury.UserField = None, | ||||
|                            key: str = None, | ||||
|                            value: str = None): | ||||
|             if field is None and (key is None or value is None): | ||||
|                 return self | ||||
|             try: | ||||
|                 self.header_dict["user_fields"] | ||||
|             except KeyError: | ||||
|                 self.header_dict["user_fields"] = [] | ||||
|             if field is not None: | ||||
|                 self.header_dict["user_fields"].append(field) | ||||
|             if key is not None and value is not None: | ||||
|                 self.header_dict["user_fields"].append( | ||||
|                     Mercury.UserField(key=key, value=value.encode())) | ||||
|             return self | ||||
| 
 | ||||
|         def add_payload_part(self, part: bytes): | ||||
|             self.payload.append(part) | ||||
|             return self | ||||
| 
 | ||||
|         def add_protobuf_payload(self, msg): | ||||
|             return self.add_payload_part(msg) | ||||
| 
 | ||||
|         def build(self): | ||||
|             return RawMercuryRequest(Mercury.Header(**self.header_dict), | ||||
|                                      self.payload) | ||||
							
								
								
									
										283
									
								
								resources/lib/librespot/metadata.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										283
									
								
								resources/lib/librespot/metadata.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,283 @@ | |||
| from __future__ import annotations | ||||
| from librespot import util | ||||
| from librespot.proto.ContextTrack_pb2 import ContextTrack | ||||
| from librespot.util import Base62 | ||||
| import re | ||||
| 
 | ||||
| 
 | ||||
| class SpotifyId: | ||||
|     STATIC_FROM_URI = "fromUri" | ||||
|     STATIC_FROM_BASE62 = "fromBase62" | ||||
|     STATIC_FROM_HEX = "fromHex" | ||||
| 
 | ||||
|     @staticmethod | ||||
|     def from_base62(base62: str): | ||||
|         raise NotImplementedError | ||||
| 
 | ||||
|     @staticmethod | ||||
|     def from_hex(hex_str: str): | ||||
|         raise NotImplementedError | ||||
| 
 | ||||
|     @staticmethod | ||||
|     def from_uri(uri: str): | ||||
|         raise NotImplementedError | ||||
| 
 | ||||
|     def to_spotify_uri(self) -> str: | ||||
|         raise NotImplementedError | ||||
| 
 | ||||
|     class SpotifyIdParsingException(Exception): | ||||
|         pass | ||||
| 
 | ||||
| 
 | ||||
| class PlayableId: | ||||
|     base62 = Base62.create_instance_with_inverted_character_set() | ||||
| 
 | ||||
|     @staticmethod | ||||
|     def from_uri(uri: str) -> PlayableId: | ||||
|         if not PlayableId.is_supported(uri): | ||||
|             return UnsupportedId(uri) | ||||
|         if TrackId.pattern.search(uri) is not None: | ||||
|             return TrackId.from_uri(uri) | ||||
|         if EpisodeId.pattern.search(uri) is not None: | ||||
|             return EpisodeId.from_uri(uri) | ||||
|         raise TypeError("Unknown uri: {}".format(uri)) | ||||
| 
 | ||||
|     @staticmethod | ||||
|     def is_supported(uri: str): | ||||
|         return (not uri.startswith("spotify:local:") | ||||
|                 and not uri == "spotify:delimiter" | ||||
|                 and not uri == "spotify:meta:delimiter") | ||||
| 
 | ||||
|     @staticmethod | ||||
|     def should_play(track: ContextTrack): | ||||
|         return track.metadata_or_default | ||||
| 
 | ||||
|     def get_gid(self) -> bytes: | ||||
|         raise NotImplementedError | ||||
| 
 | ||||
|     def hex_id(self) -> str: | ||||
|         raise NotImplementedError | ||||
| 
 | ||||
|     def to_spotify_uri(self) -> str: | ||||
|         raise NotImplementedError | ||||
| 
 | ||||
| 
 | ||||
| class PlaylistId(SpotifyId): | ||||
|     base62 = Base62.create_instance_with_inverted_character_set() | ||||
|     pattern = re.compile(r"spotify:playlist:(.{22})") | ||||
|     __id: str | ||||
| 
 | ||||
|     def __init__(self, _id: str): | ||||
|         self.__id = _id | ||||
| 
 | ||||
|     @staticmethod | ||||
|     def from_uri(uri: str) -> PlaylistId: | ||||
|         matcher = PlaylistId.pattern.search(uri) | ||||
|         if matcher is not None: | ||||
|             playlist_id = matcher.group(1) | ||||
|             return PlaylistId(playlist_id) | ||||
|         raise TypeError("Not a Spotify playlist ID: {}.".format(uri)) | ||||
| 
 | ||||
|     def id(self) -> str: | ||||
|         return self.__id | ||||
| 
 | ||||
|     def to_spotify_uri(self) -> str: | ||||
|         return "spotify:playlist:" + self.__id | ||||
| 
 | ||||
| 
 | ||||
| class UnsupportedId(PlayableId): | ||||
|     uri: str | ||||
| 
 | ||||
|     def __init__(self, uri: str): | ||||
|         self.uri = uri | ||||
| 
 | ||||
|     def get_gid(self) -> bytes: | ||||
|         raise TypeError() | ||||
| 
 | ||||
|     def hex_id(self) -> str: | ||||
|         raise TypeError() | ||||
| 
 | ||||
|     def to_spotify_uri(self) -> str: | ||||
|         return self.uri | ||||
| 
 | ||||
| 
 | ||||
| class AlbumId(SpotifyId): | ||||
|     base62 = Base62.create_instance_with_inverted_character_set() | ||||
|     pattern = re.compile(r"spotify:album:(.{22})") | ||||
|     __hex_id: str | ||||
| 
 | ||||
|     def __init__(self, hex_id: str): | ||||
|         self.__hex_id = hex_id.lower() | ||||
| 
 | ||||
|     @staticmethod | ||||
|     def from_uri(uri: str) -> AlbumId: | ||||
|         matcher = AlbumId.pattern.search(uri) | ||||
|         if matcher is not None: | ||||
|             album_id = matcher.group(1) | ||||
|             return AlbumId(util.bytes_to_hex(AlbumId.base62.decode(album_id.encode(), 16))) | ||||
|         raise TypeError("Not a Spotify album ID: {}.".format(uri)) | ||||
| 
 | ||||
|     @staticmethod | ||||
|     def from_base62(base62: str) -> AlbumId: | ||||
|         return AlbumId(util.bytes_to_hex(AlbumId.base62.decode(base62.encode(), 16))) | ||||
| 
 | ||||
|     @staticmethod | ||||
|     def from_hex(hex_str: str) -> AlbumId: | ||||
|         return AlbumId(hex_str) | ||||
| 
 | ||||
|     def to_mercury_uri(self) -> str: | ||||
|         return "hm://metadata/4/album/{}".format(self.__hex_id) | ||||
| 
 | ||||
|     def hex_id(self) -> str: | ||||
|         return self.__hex_id | ||||
| 
 | ||||
|     def to_spotify_uri(self) -> str: | ||||
|         return "spotify:album:{}".format( | ||||
|             AlbumId.base62.encode(util.hex_to_bytes(self.__hex_id)).decode()) | ||||
| 
 | ||||
| 
 | ||||
| class ArtistId(SpotifyId): | ||||
|     base62 = Base62.create_instance_with_inverted_character_set() | ||||
|     pattern = re.compile("spotify:artist:(.{22})") | ||||
|     __hex_id: str | ||||
| 
 | ||||
|     def __init__(self, hex_id: str): | ||||
|         self.__hex_id = hex_id.lower() | ||||
| 
 | ||||
|     @staticmethod | ||||
|     def from_uri(uri: str) -> ArtistId: | ||||
|         matcher = ArtistId.pattern.search(uri) | ||||
|         if matcher is not None: | ||||
|             artist_id = matcher.group(1) | ||||
|             return ArtistId( | ||||
|                 util.bytes_to_hex(ArtistId.base62.decode(artist_id.encode(), 16))) | ||||
|         raise TypeError("Not a Spotify artist ID: {}".format(uri)) | ||||
| 
 | ||||
|     @staticmethod | ||||
|     def from_base62(base62: str) -> ArtistId: | ||||
|         return ArtistId(util.bytes_to_hex(ArtistId.base62.decode(base62.encode(), 16))) | ||||
| 
 | ||||
|     @staticmethod | ||||
|     def from_hex(hex_str: str) -> ArtistId: | ||||
|         return ArtistId(hex_str) | ||||
| 
 | ||||
|     def to_mercury_uri(self) -> str: | ||||
|         return "hm://metadata/4/artist/{}".format(self.__hex_id) | ||||
| 
 | ||||
|     def to_spotify_uri(self) -> str: | ||||
|         return "spotify:artist:{}".format( | ||||
|             ArtistId.base62.encode(util.hex_to_bytes(self.__hex_id)).decode()) | ||||
| 
 | ||||
|     def hex_id(self) -> str: | ||||
|         return self.__hex_id | ||||
| 
 | ||||
| 
 | ||||
| class EpisodeId(SpotifyId, PlayableId): | ||||
|     pattern = re.compile(r"spotify:episode:(.{22})") | ||||
|     __hex_id: str | ||||
| 
 | ||||
|     def __init__(self, hex_id: str): | ||||
|         self.__hex_id = hex_id.lower() | ||||
| 
 | ||||
|     @staticmethod | ||||
|     def from_uri(uri: str) -> EpisodeId: | ||||
|         matcher = EpisodeId.pattern.search(uri) | ||||
|         if matcher is not None: | ||||
|             episode_id = matcher.group(1) | ||||
|             return EpisodeId( | ||||
|                 util.bytes_to_hex(PlayableId.base62.decode(episode_id.encode(), 16))) | ||||
|         raise TypeError("Not a Spotify episode ID: {}".format(uri)) | ||||
| 
 | ||||
|     @staticmethod | ||||
|     def from_base62(base62: str) -> EpisodeId: | ||||
|         return EpisodeId( | ||||
|             util.bytes_to_hex(PlayableId.base62.decode(base62.encode(), 16))) | ||||
| 
 | ||||
|     @staticmethod | ||||
|     def from_hex(hex_str: str) -> EpisodeId: | ||||
|         return EpisodeId(hex_str) | ||||
| 
 | ||||
|     def to_mercury_uri(self) -> str: | ||||
|         return "hm://metadata/4/episode/{}".format(self.__hex_id) | ||||
| 
 | ||||
|     def to_spotify_uri(self) -> str: | ||||
|         return "Spotify:episode:{}".format( | ||||
|             PlayableId.base62.encode(util.hex_to_bytes(self.__hex_id)).decode()) | ||||
| 
 | ||||
|     def hex_id(self) -> str: | ||||
|         return self.__hex_id | ||||
| 
 | ||||
|     def get_gid(self) -> bytes: | ||||
|         return util.hex_to_bytes(self.__hex_id) | ||||
| 
 | ||||
| 
 | ||||
| class ShowId(SpotifyId): | ||||
|     base62 = Base62.create_instance_with_inverted_character_set() | ||||
|     pattern = re.compile("spotify:show:(.{22})") | ||||
|     __hex_id: str | ||||
| 
 | ||||
|     def __init__(self, hex_id: str): | ||||
|         self.__hex_id = hex_id | ||||
| 
 | ||||
|     @staticmethod | ||||
|     def from_uri(uri: str) -> ShowId: | ||||
|         matcher = ShowId.pattern.search(uri) | ||||
|         if matcher is not None: | ||||
|             show_id = matcher.group(1) | ||||
|             return ShowId(util.bytes_to_hex(ShowId.base62.decode(show_id.encode(), 16))) | ||||
|         raise TypeError("Not a Spotify show ID: {}".format(uri)) | ||||
| 
 | ||||
|     @staticmethod | ||||
|     def from_base62(base62: str) -> ShowId: | ||||
|         return ShowId(util.bytes_to_hex(ShowId.base62.decode(base62.encode(), 16))) | ||||
| 
 | ||||
|     @staticmethod | ||||
|     def from_hex(hex_str: str) -> ShowId: | ||||
|         return ShowId(hex_str) | ||||
| 
 | ||||
|     def to_mercury_uri(self) -> str: | ||||
|         return "hm://metadata/4/show/{}".format(self.__hex_id) | ||||
| 
 | ||||
|     def to_spotify_uri(self) -> str: | ||||
|         return "spotify:show:{}".format( | ||||
|             ShowId.base62.encode(util.hex_to_bytes(self.__hex_id)).decode()) | ||||
| 
 | ||||
|     def hex_id(self) -> str: | ||||
|         return self.__hex_id | ||||
| 
 | ||||
| 
 | ||||
| class TrackId(PlayableId, SpotifyId): | ||||
|     pattern = re.compile("spotify:track:(.{22})") | ||||
|     __hex_id: str | ||||
| 
 | ||||
|     def __init__(self, hex_id: str): | ||||
|         self.__hex_id = hex_id.lower() | ||||
| 
 | ||||
|     @staticmethod | ||||
|     def from_uri(uri: str) -> TrackId: | ||||
|         search = TrackId.pattern.search(uri) | ||||
|         if search is not None: | ||||
|             track_id = search.group(1) | ||||
|             return TrackId( | ||||
|                 util.bytes_to_hex(PlayableId.base62.decode(track_id.encode(), 16))) | ||||
|         raise RuntimeError("Not a Spotify track ID: {}".format(uri)) | ||||
| 
 | ||||
|     @staticmethod | ||||
|     def from_base62(base62: str) -> TrackId: | ||||
|         return TrackId(util.bytes_to_hex(PlayableId.base62.decode(base62.encode(), 16))) | ||||
| 
 | ||||
|     @staticmethod | ||||
|     def from_hex(hex_str: str) -> TrackId: | ||||
|         return TrackId(hex_str) | ||||
| 
 | ||||
|     def to_mercury_uri(self) -> str: | ||||
|         return "hm://metadata/4/track/{}".format(self.__hex_id) | ||||
| 
 | ||||
|     def to_spotify_uri(self) -> str: | ||||
|         return "spotify:track:{}".format(TrackId.base62.encode(util.hex_to_bytes(self.__hex_id)).decode()) | ||||
| 
 | ||||
|     def hex_id(self) -> str: | ||||
|         return self.__hex_id | ||||
| 
 | ||||
|     def get_gid(self) -> bytes: | ||||
|         return util.hex_to_bytes(self.__hex_id) | ||||
							
								
								
									
										1984
									
								
								resources/lib/librespot/proto/Authentication_pb2.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1984
									
								
								resources/lib/librespot/proto/Authentication_pb2.py
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										91
									
								
								resources/lib/librespot/proto/CanvazMeta_pb2.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								resources/lib/librespot/proto/CanvazMeta_pb2.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,91 @@ | |||
| # -*- coding: utf-8 -*- | ||||
| # Generated by the protocol buffer compiler.  DO NOT EDIT! | ||||
| # source: canvaz-meta.proto | ||||
| """Generated protocol buffer code.""" | ||||
| from google.protobuf import descriptor as _descriptor | ||||
| from google.protobuf import message as _message | ||||
| from google.protobuf import reflection as _reflection | ||||
| from google.protobuf import symbol_database as _symbol_database | ||||
| from google.protobuf.internal import enum_type_wrapper | ||||
| 
 | ||||
| # @@protoc_insertion_point(imports) | ||||
| 
 | ||||
| _sym_db = _symbol_database.Default() | ||||
| 
 | ||||
| DESCRIPTOR = _descriptor.FileDescriptor( | ||||
|     name="canvaz-meta.proto", | ||||
|     package="com.spotify.canvaz", | ||||
|     syntax="proto3", | ||||
|     serialized_options=b"\n\022com.spotify.canvazH\002", | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     serialized_pb= | ||||
|     b"\n\x11\x63\x61nvaz-meta.proto\x12\x12\x63om.spotify.canvaz*R\n\x04Type\x12\t\n\x05IMAGE\x10\x00\x12\t\n\x05VIDEO\x10\x01\x12\x11\n\rVIDEO_LOOPING\x10\x02\x12\x18\n\x14VIDEO_LOOPING_RANDOM\x10\x03\x12\x07\n\x03GIF\x10\x04\x42\x16\n\x12\x63om.spotify.canvazH\x02\x62\x06proto3", | ||||
| ) | ||||
| 
 | ||||
| _TYPE = _descriptor.EnumDescriptor( | ||||
|     name="Type", | ||||
|     full_name="com.spotify.canvaz.Type", | ||||
|     filename=None, | ||||
|     file=DESCRIPTOR, | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     values=[ | ||||
|         _descriptor.EnumValueDescriptor( | ||||
|             name="IMAGE", | ||||
|             index=0, | ||||
|             number=0, | ||||
|             serialized_options=None, | ||||
|             type=None, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.EnumValueDescriptor( | ||||
|             name="VIDEO", | ||||
|             index=1, | ||||
|             number=1, | ||||
|             serialized_options=None, | ||||
|             type=None, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.EnumValueDescriptor( | ||||
|             name="VIDEO_LOOPING", | ||||
|             index=2, | ||||
|             number=2, | ||||
|             serialized_options=None, | ||||
|             type=None, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.EnumValueDescriptor( | ||||
|             name="VIDEO_LOOPING_RANDOM", | ||||
|             index=3, | ||||
|             number=3, | ||||
|             serialized_options=None, | ||||
|             type=None, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.EnumValueDescriptor( | ||||
|             name="GIF", | ||||
|             index=4, | ||||
|             number=4, | ||||
|             serialized_options=None, | ||||
|             type=None, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|     ], | ||||
|     containing_type=None, | ||||
|     serialized_options=None, | ||||
|     serialized_start=41, | ||||
|     serialized_end=123, | ||||
| ) | ||||
| _sym_db.RegisterEnumDescriptor(_TYPE) | ||||
| 
 | ||||
| Type = enum_type_wrapper.EnumTypeWrapper(_TYPE) | ||||
| IMAGE = 0 | ||||
| VIDEO = 1 | ||||
| VIDEO_LOOPING = 2 | ||||
| VIDEO_LOOPING_RANDOM = 3 | ||||
| GIF = 4 | ||||
| 
 | ||||
| DESCRIPTOR.enum_types_by_name["Type"] = _TYPE | ||||
| _sym_db.RegisterFileDescriptor(DESCRIPTOR) | ||||
| 
 | ||||
| DESCRIPTOR._options = None | ||||
| # @@protoc_insertion_point(module_scope) | ||||
							
								
								
									
										564
									
								
								resources/lib/librespot/proto/Canvaz_pb2.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										564
									
								
								resources/lib/librespot/proto/Canvaz_pb2.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,564 @@ | |||
| # -*- coding: utf-8 -*- | ||||
| # Generated by the protocol buffer compiler.  DO NOT EDIT! | ||||
| # source: canvaz.proto | ||||
| """Generated protocol buffer code.""" | ||||
| import CanvazMeta_pb2 as canvaz__meta__pb2 | ||||
| from google.protobuf import descriptor as _descriptor | ||||
| from google.protobuf import message as _message | ||||
| from google.protobuf import reflection as _reflection | ||||
| from google.protobuf import symbol_database as _symbol_database | ||||
| 
 | ||||
| # @@protoc_insertion_point(imports) | ||||
| 
 | ||||
| _sym_db = _symbol_database.Default() | ||||
| 
 | ||||
| DESCRIPTOR = _descriptor.FileDescriptor( | ||||
|     name="canvaz.proto", | ||||
|     package="com.spotify.canvazcache", | ||||
|     syntax="proto3", | ||||
|     serialized_options=b"\n\022com.spotify.canvazH\002", | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     serialized_pb= | ||||
|     b'\n\x0c\x63\x61nvaz.proto\x12\x17\x63om.spotify.canvazcache\x1a\x11\x63\x61nvaz-meta.proto"3\n\x06\x41rtist\x12\x0b\n\x03uri\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x0e\n\x06\x61vatar\x18\x03 \x01(\t"\xe1\x02\n\x14\x45ntityCanvazResponse\x12\x46\n\x08\x63\x61nvases\x18\x01 \x03(\x0b\x32\x34.com.spotify.canvazcache.EntityCanvazResponse.Canvaz\x12\x16\n\x0ettl_in_seconds\x18\x02 \x01(\x03\x1a\xe8\x01\n\x06\x43\x61nvaz\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0b\n\x03url\x18\x02 \x01(\t\x12\x0f\n\x07\x66ile_id\x18\x03 \x01(\t\x12&\n\x04type\x18\x04 \x01(\x0e\x32\x18.com.spotify.canvaz.Type\x12\x12\n\nentity_uri\x18\x05 \x01(\t\x12/\n\x06\x61rtist\x18\x06 \x01(\x0b\x32\x1f.com.spotify.canvazcache.Artist\x12\x10\n\x08\x65xplicit\x18\x07 \x01(\x08\x12\x13\n\x0buploaded_by\x18\x08 \x01(\t\x12\x0c\n\x04\x65tag\x18\t \x01(\t\x12\x12\n\ncanvas_uri\x18\x0b \x01(\t"\x88\x01\n\x13\x45ntityCanvazRequest\x12\x45\n\x08\x65ntities\x18\x01 \x03(\x0b\x32\x33.com.spotify.canvazcache.EntityCanvazRequest.Entity\x1a*\n\x06\x45ntity\x12\x12\n\nentity_uri\x18\x01 \x01(\t\x12\x0c\n\x04\x65tag\x18\x02 \x01(\tB\x16\n\x12\x63om.spotify.canvazH\x02\x62\x06proto3', | ||||
|     dependencies=[ | ||||
|         canvaz__meta__pb2.DESCRIPTOR, | ||||
|     ], | ||||
| ) | ||||
| 
 | ||||
| _ARTIST = _descriptor.Descriptor( | ||||
|     name="Artist", | ||||
|     full_name="com.spotify.canvazcache.Artist", | ||||
|     filename=None, | ||||
|     file=DESCRIPTOR, | ||||
|     containing_type=None, | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     fields=[ | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="uri", | ||||
|             full_name="com.spotify.canvazcache.Artist.uri", | ||||
|             index=0, | ||||
|             number=1, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"".decode("utf-8"), | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="name", | ||||
|             full_name="com.spotify.canvazcache.Artist.name", | ||||
|             index=1, | ||||
|             number=2, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"".decode("utf-8"), | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="avatar", | ||||
|             full_name="com.spotify.canvazcache.Artist.avatar", | ||||
|             index=2, | ||||
|             number=3, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"".decode("utf-8"), | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|     ], | ||||
|     extensions=[], | ||||
|     nested_types=[], | ||||
|     enum_types=[], | ||||
|     serialized_options=None, | ||||
|     is_extendable=False, | ||||
|     syntax="proto3", | ||||
|     extension_ranges=[], | ||||
|     oneofs=[], | ||||
|     serialized_start=60, | ||||
|     serialized_end=111, | ||||
| ) | ||||
| 
 | ||||
| _ENTITYCANVAZRESPONSE_CANVAZ = _descriptor.Descriptor( | ||||
|     name="Canvaz", | ||||
|     full_name="com.spotify.canvazcache.EntityCanvazResponse.Canvaz", | ||||
|     filename=None, | ||||
|     file=DESCRIPTOR, | ||||
|     containing_type=None, | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     fields=[ | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="id", | ||||
|             full_name="com.spotify.canvazcache.EntityCanvazResponse.Canvaz.id", | ||||
|             index=0, | ||||
|             number=1, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"".decode("utf-8"), | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="url", | ||||
|             full_name="com.spotify.canvazcache.EntityCanvazResponse.Canvaz.url", | ||||
|             index=1, | ||||
|             number=2, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"".decode("utf-8"), | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="file_id", | ||||
|             full_name= | ||||
|             "com.spotify.canvazcache.EntityCanvazResponse.Canvaz.file_id", | ||||
|             index=2, | ||||
|             number=3, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"".decode("utf-8"), | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="type", | ||||
|             full_name= | ||||
|             "com.spotify.canvazcache.EntityCanvazResponse.Canvaz.type", | ||||
|             index=3, | ||||
|             number=4, | ||||
|             type=14, | ||||
|             cpp_type=8, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=0, | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="entity_uri", | ||||
|             full_name= | ||||
|             "com.spotify.canvazcache.EntityCanvazResponse.Canvaz.entity_uri", | ||||
|             index=4, | ||||
|             number=5, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"".decode("utf-8"), | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="artist", | ||||
|             full_name= | ||||
|             "com.spotify.canvazcache.EntityCanvazResponse.Canvaz.artist", | ||||
|             index=5, | ||||
|             number=6, | ||||
|             type=11, | ||||
|             cpp_type=10, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=None, | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="explicit", | ||||
|             full_name= | ||||
|             "com.spotify.canvazcache.EntityCanvazResponse.Canvaz.explicit", | ||||
|             index=6, | ||||
|             number=7, | ||||
|             type=8, | ||||
|             cpp_type=7, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=False, | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="uploaded_by", | ||||
|             full_name= | ||||
|             "com.spotify.canvazcache.EntityCanvazResponse.Canvaz.uploaded_by", | ||||
|             index=7, | ||||
|             number=8, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"".decode("utf-8"), | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="etag", | ||||
|             full_name= | ||||
|             "com.spotify.canvazcache.EntityCanvazResponse.Canvaz.etag", | ||||
|             index=8, | ||||
|             number=9, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"".decode("utf-8"), | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="canvas_uri", | ||||
|             full_name= | ||||
|             "com.spotify.canvazcache.EntityCanvazResponse.Canvaz.canvas_uri", | ||||
|             index=9, | ||||
|             number=11, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"".decode("utf-8"), | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|     ], | ||||
|     extensions=[], | ||||
|     nested_types=[], | ||||
|     enum_types=[], | ||||
|     serialized_options=None, | ||||
|     is_extendable=False, | ||||
|     syntax="proto3", | ||||
|     extension_ranges=[], | ||||
|     oneofs=[], | ||||
|     serialized_start=235, | ||||
|     serialized_end=467, | ||||
| ) | ||||
| 
 | ||||
| _ENTITYCANVAZRESPONSE = _descriptor.Descriptor( | ||||
|     name="EntityCanvazResponse", | ||||
|     full_name="com.spotify.canvazcache.EntityCanvazResponse", | ||||
|     filename=None, | ||||
|     file=DESCRIPTOR, | ||||
|     containing_type=None, | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     fields=[ | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="canvases", | ||||
|             full_name="com.spotify.canvazcache.EntityCanvazResponse.canvases", | ||||
|             index=0, | ||||
|             number=1, | ||||
|             type=11, | ||||
|             cpp_type=10, | ||||
|             label=3, | ||||
|             has_default_value=False, | ||||
|             default_value=[], | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="ttl_in_seconds", | ||||
|             full_name= | ||||
|             "com.spotify.canvazcache.EntityCanvazResponse.ttl_in_seconds", | ||||
|             index=1, | ||||
|             number=2, | ||||
|             type=3, | ||||
|             cpp_type=2, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=0, | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|     ], | ||||
|     extensions=[], | ||||
|     nested_types=[ | ||||
|         _ENTITYCANVAZRESPONSE_CANVAZ, | ||||
|     ], | ||||
|     enum_types=[], | ||||
|     serialized_options=None, | ||||
|     is_extendable=False, | ||||
|     syntax="proto3", | ||||
|     extension_ranges=[], | ||||
|     oneofs=[], | ||||
|     serialized_start=114, | ||||
|     serialized_end=467, | ||||
| ) | ||||
| 
 | ||||
| _ENTITYCANVAZREQUEST_ENTITY = _descriptor.Descriptor( | ||||
|     name="Entity", | ||||
|     full_name="com.spotify.canvazcache.EntityCanvazRequest.Entity", | ||||
|     filename=None, | ||||
|     file=DESCRIPTOR, | ||||
|     containing_type=None, | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     fields=[ | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="entity_uri", | ||||
|             full_name= | ||||
|             "com.spotify.canvazcache.EntityCanvazRequest.Entity.entity_uri", | ||||
|             index=0, | ||||
|             number=1, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"".decode("utf-8"), | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="etag", | ||||
|             full_name="com.spotify.canvazcache.EntityCanvazRequest.Entity.etag", | ||||
|             index=1, | ||||
|             number=2, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"".decode("utf-8"), | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|     ], | ||||
|     extensions=[], | ||||
|     nested_types=[], | ||||
|     enum_types=[], | ||||
|     serialized_options=None, | ||||
|     is_extendable=False, | ||||
|     syntax="proto3", | ||||
|     extension_ranges=[], | ||||
|     oneofs=[], | ||||
|     serialized_start=564, | ||||
|     serialized_end=606, | ||||
| ) | ||||
| 
 | ||||
| _ENTITYCANVAZREQUEST = _descriptor.Descriptor( | ||||
|     name="EntityCanvazRequest", | ||||
|     full_name="com.spotify.canvazcache.EntityCanvazRequest", | ||||
|     filename=None, | ||||
|     file=DESCRIPTOR, | ||||
|     containing_type=None, | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     fields=[ | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="entities", | ||||
|             full_name="com.spotify.canvazcache.EntityCanvazRequest.entities", | ||||
|             index=0, | ||||
|             number=1, | ||||
|             type=11, | ||||
|             cpp_type=10, | ||||
|             label=3, | ||||
|             has_default_value=False, | ||||
|             default_value=[], | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|     ], | ||||
|     extensions=[], | ||||
|     nested_types=[ | ||||
|         _ENTITYCANVAZREQUEST_ENTITY, | ||||
|     ], | ||||
|     enum_types=[], | ||||
|     serialized_options=None, | ||||
|     is_extendable=False, | ||||
|     syntax="proto3", | ||||
|     extension_ranges=[], | ||||
|     oneofs=[], | ||||
|     serialized_start=470, | ||||
|     serialized_end=606, | ||||
| ) | ||||
| 
 | ||||
| _ENTITYCANVAZRESPONSE_CANVAZ.fields_by_name[ | ||||
|     "type"].enum_type = canvaz__meta__pb2._TYPE | ||||
| _ENTITYCANVAZRESPONSE_CANVAZ.fields_by_name["artist"].message_type = _ARTIST | ||||
| _ENTITYCANVAZRESPONSE_CANVAZ.containing_type = _ENTITYCANVAZRESPONSE | ||||
| _ENTITYCANVAZRESPONSE.fields_by_name[ | ||||
|     "canvases"].message_type = _ENTITYCANVAZRESPONSE_CANVAZ | ||||
| _ENTITYCANVAZREQUEST_ENTITY.containing_type = _ENTITYCANVAZREQUEST | ||||
| _ENTITYCANVAZREQUEST.fields_by_name[ | ||||
|     "entities"].message_type = _ENTITYCANVAZREQUEST_ENTITY | ||||
| DESCRIPTOR.message_types_by_name["Artist"] = _ARTIST | ||||
| DESCRIPTOR.message_types_by_name[ | ||||
|     "EntityCanvazResponse"] = _ENTITYCANVAZRESPONSE | ||||
| DESCRIPTOR.message_types_by_name["EntityCanvazRequest"] = _ENTITYCANVAZREQUEST | ||||
| _sym_db.RegisterFileDescriptor(DESCRIPTOR) | ||||
| 
 | ||||
| Artist = _reflection.GeneratedProtocolMessageType( | ||||
|     "Artist", | ||||
|     (_message.Message, ), | ||||
|     { | ||||
|         "DESCRIPTOR": _ARTIST, | ||||
|         "__module__": "canvaz_pb2" | ||||
|         # @@protoc_insertion_point(class_scope:com.spotify.canvazcache.Artist) | ||||
|     }, | ||||
| ) | ||||
| _sym_db.RegisterMessage(Artist) | ||||
| 
 | ||||
| EntityCanvazResponse = _reflection.GeneratedProtocolMessageType( | ||||
|     "EntityCanvazResponse", | ||||
|     (_message.Message, ), | ||||
|     { | ||||
|         "Canvaz": | ||||
|         _reflection.GeneratedProtocolMessageType( | ||||
|             "Canvaz", | ||||
|             (_message.Message, ), | ||||
|             { | ||||
|                 "DESCRIPTOR": _ENTITYCANVAZRESPONSE_CANVAZ, | ||||
|                 "__module__": "canvaz_pb2" | ||||
|                 # @@protoc_insertion_point(class_scope:com.spotify.canvazcache.EntityCanvazResponse.Canvaz) | ||||
|             }, | ||||
|         ), | ||||
|         "DESCRIPTOR": | ||||
|         _ENTITYCANVAZRESPONSE, | ||||
|         "__module__": | ||||
|         "canvaz_pb2" | ||||
|         # @@protoc_insertion_point(class_scope:com.spotify.canvazcache.EntityCanvazResponse) | ||||
|     }, | ||||
| ) | ||||
| _sym_db.RegisterMessage(EntityCanvazResponse) | ||||
| _sym_db.RegisterMessage(EntityCanvazResponse.Canvaz) | ||||
| 
 | ||||
| EntityCanvazRequest = _reflection.GeneratedProtocolMessageType( | ||||
|     "EntityCanvazRequest", | ||||
|     (_message.Message, ), | ||||
|     { | ||||
|         "Entity": | ||||
|         _reflection.GeneratedProtocolMessageType( | ||||
|             "Entity", | ||||
|             (_message.Message, ), | ||||
|             { | ||||
|                 "DESCRIPTOR": _ENTITYCANVAZREQUEST_ENTITY, | ||||
|                 "__module__": "canvaz_pb2" | ||||
|                 # @@protoc_insertion_point(class_scope:com.spotify.canvazcache.EntityCanvazRequest.Entity) | ||||
|             }, | ||||
|         ), | ||||
|         "DESCRIPTOR": | ||||
|         _ENTITYCANVAZREQUEST, | ||||
|         "__module__": | ||||
|         "canvaz_pb2" | ||||
|         # @@protoc_insertion_point(class_scope:com.spotify.canvazcache.EntityCanvazRequest) | ||||
|     }, | ||||
| ) | ||||
| _sym_db.RegisterMessage(EntityCanvazRequest) | ||||
| _sym_db.RegisterMessage(EntityCanvazRequest.Entity) | ||||
| 
 | ||||
| DESCRIPTOR._options = None | ||||
| # @@protoc_insertion_point(module_scope) | ||||
							
								
								
									
										63
									
								
								resources/lib/librespot/proto/ClientToken_pb2.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								resources/lib/librespot/proto/ClientToken_pb2.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,63 @@ | |||
| # -*- coding: utf-8 -*- | ||||
| # Generated by the protocol buffer compiler.  DO NOT EDIT! | ||||
| # source: client_token.proto | ||||
| """Generated protocol buffer code.""" | ||||
| from google.protobuf.internal import builder as _builder | ||||
| from google.protobuf import descriptor as _descriptor | ||||
| from google.protobuf import descriptor_pool as _descriptor_pool | ||||
| from google.protobuf import symbol_database as _symbol_database | ||||
| # @@protoc_insertion_point(imports) | ||||
| 
 | ||||
| _sym_db = _symbol_database.Default() | ||||
| 
 | ||||
| 
 | ||||
| from librespot.proto import Connectivity_pb2 as connectivity__pb2 | ||||
| 
 | ||||
| 
 | ||||
| DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x12\x63lient_token.proto\x12\x1bspotify.clienttoken.http.v0\x1a\x12\x63onnectivity.proto\"\x84\x02\n\x12\x43lientTokenRequest\x12I\n\x0crequest_type\x18\x01 \x01(\x0e\x32\x33.spotify.clienttoken.http.v0.ClientTokenRequestType\x12\x45\n\x0b\x63lient_data\x18\x02 \x01(\x0b\x32..spotify.clienttoken.http.v0.ClientDataRequestH\x00\x12Q\n\x11\x63hallenge_answers\x18\x03 \x01(\x0b\x32\x34.spotify.clienttoken.http.v0.ChallengeAnswersRequestH\x00\x42\t\n\x07request\"\x99\x01\n\x11\x43lientDataRequest\x12\x16\n\x0e\x63lient_version\x18\x01 \x01(\t\x12\x11\n\tclient_id\x18\x02 \x01(\t\x12Q\n\x15\x63onnectivity_sdk_data\x18\x03 \x01(\x0b\x32\x30.spotify.clienttoken.data.v0.ConnectivitySdkDataH\x00\x42\x06\n\x04\x64\x61ta\"g\n\x17\x43hallengeAnswersRequest\x12\r\n\x05state\x18\x01 \x01(\t\x12=\n\x07\x61nswers\x18\x02 \x03(\x0b\x32,.spotify.clienttoken.http.v0.ChallengeAnswer\"\x81\x02\n\x13\x43lientTokenResponse\x12K\n\rresponse_type\x18\x01 \x01(\x0e\x32\x34.spotify.clienttoken.http.v0.ClientTokenResponseType\x12J\n\rgranted_token\x18\x02 \x01(\x0b\x32\x31.spotify.clienttoken.http.v0.GrantedTokenResponseH\x00\x12\x45\n\nchallenges\x18\x03 \x01(\x0b\x32/.spotify.clienttoken.http.v0.ChallengesResponseH\x00\x42\n\n\x08response\"\x1d\n\x0bTokenDomain\x12\x0e\n\x06\x64omain\x18\x01 \x01(\t\"\x9e\x01\n\x14GrantedTokenResponse\x12\r\n\x05token\x18\x01 \x01(\t\x12\x1d\n\x15\x65xpires_after_seconds\x18\x02 \x01(\x05\x12\x1d\n\x15refresh_after_seconds\x18\x03 \x01(\x05\x12\x39\n\x07\x64omains\x18\x04 \x03(\x0b\x32(.spotify.clienttoken.http.v0.TokenDomain\"_\n\x12\x43hallengesResponse\x12\r\n\x05state\x18\x01 \x01(\t\x12:\n\nchallenges\x18\x02 \x03(\x0b\x32&.spotify.clienttoken.http.v0.Challenge\"&\n\x16\x43lientSecretParameters\x12\x0c\n\x04salt\x18\x01 \x01(\t\"7\n\x14\x45valuateJSParameters\x12\x0c\n\x04\x63ode\x18\x01 \x01(\t\x12\x11\n\tlibraries\x18\x02 \x03(\t\"4\n\x12HashCashParameters\x12\x0e\n\x06length\x18\x01 \x01(\x05\x12\x0e\n\x06prefix\x18\x02 \x01(\t\"\xda\x02\n\tChallenge\x12\x38\n\x04type\x18\x01 \x01(\x0e\x32*.spotify.clienttoken.http.v0.ChallengeType\x12W\n\x18\x63lient_secret_parameters\x18\x02 \x01(\x0b\x32\x33.spotify.clienttoken.http.v0.ClientSecretParametersH\x00\x12S\n\x16\x65valuate_js_parameters\x18\x03 \x01(\x0b\x32\x31.spotify.clienttoken.http.v0.EvaluateJSParametersH\x00\x12W\n\x1c\x65valuate_hashcash_parameters\x18\x04 \x01(\x0b\x32/.spotify.clienttoken.http.v0.HashCashParametersH\x00\x42\x0c\n\nparameters\"&\n\x16\x43lientSecretHMACAnswer\x12\x0c\n\x04hmac\x18\x01 \x01(\t\"\"\n\x10\x45valuateJSAnswer\x12\x0e\n\x06result\x18\x01 \x01(\t\" \n\x0eHashCashAnswer\x12\x0e\n\x06suffix\x18\x01 \x01(\t\"\xb4\x02\n\x0f\x43hallengeAnswer\x12\x41\n\rChallengeType\x18\x01 \x01(\x0e\x32*.spotify.clienttoken.http.v0.ChallengeType\x12L\n\rclient_secret\x18\x02 \x01(\x0b\x32\x33.spotify.clienttoken.http.v0.ClientSecretHMACAnswerH\x00\x12\x44\n\x0b\x65valuate_js\x18\x03 \x01(\x0b\x32-.spotify.clienttoken.http.v0.EvaluateJSAnswerH\x00\x12@\n\thash_cash\x18\x04 \x01(\x0b\x32+.spotify.clienttoken.http.v0.HashCashAnswerH\x00\x42\x08\n\x06\x61nswer\"(\n\x15\x43lientTokenBadRequest\x12\x0f\n\x07message\x18\x01 \x01(\t*u\n\x16\x43lientTokenRequestType\x12\x13\n\x0fREQUEST_UNKNOWN\x10\x00\x12\x1f\n\x1bREQUEST_CLIENT_DATA_REQUEST\x10\x01\x12%\n!REQUEST_CHALLENGE_ANSWERS_REQUEST\x10\x02*v\n\x17\x43lientTokenResponseType\x12\x14\n\x10RESPONSE_UNKNOWN\x10\x00\x12#\n\x1fRESPONSE_GRANTED_TOKEN_RESPONSE\x10\x01\x12 \n\x1cRESPONSE_CHALLENGES_RESPONSE\x10\x02*|\n\rChallengeType\x12\x15\n\x11\x43HALLENGE_UNKNOWN\x10\x00\x12 \n\x1c\x43HALLENGE_CLIENT_SECRET_HMAC\x10\x01\x12\x19\n\x15\x43HALLENGE_EVALUATE_JS\x10\x02\x12\x17\n\x13\x43HALLENGE_HASH_CASH\x10\x03\x42#\n\x1f\x63om.spotify.clienttoken.http.v0H\x02\x62\x06proto3') | ||||
| 
 | ||||
| _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) | ||||
| _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'client_token_pb2', globals()) | ||||
| if _descriptor._USE_C_DESCRIPTORS == False: | ||||
| 
 | ||||
|   DESCRIPTOR._options = None | ||||
|   DESCRIPTOR._serialized_options = b'\n\037com.spotify.clienttoken.http.v0H\002' | ||||
|   _CLIENTTOKENREQUESTTYPE._serialized_start=2107 | ||||
|   _CLIENTTOKENREQUESTTYPE._serialized_end=2224 | ||||
|   _CLIENTTOKENRESPONSETYPE._serialized_start=2226 | ||||
|   _CLIENTTOKENRESPONSETYPE._serialized_end=2344 | ||||
|   _CHALLENGETYPE._serialized_start=2346 | ||||
|   _CHALLENGETYPE._serialized_end=2470 | ||||
|   _CLIENTTOKENREQUEST._serialized_start=72 | ||||
|   _CLIENTTOKENREQUEST._serialized_end=332 | ||||
|   _CLIENTDATAREQUEST._serialized_start=335 | ||||
|   _CLIENTDATAREQUEST._serialized_end=488 | ||||
|   _CHALLENGEANSWERSREQUEST._serialized_start=490 | ||||
|   _CHALLENGEANSWERSREQUEST._serialized_end=593 | ||||
|   _CLIENTTOKENRESPONSE._serialized_start=596 | ||||
|   _CLIENTTOKENRESPONSE._serialized_end=853 | ||||
|   _TOKENDOMAIN._serialized_start=855 | ||||
|   _TOKENDOMAIN._serialized_end=884 | ||||
|   _GRANTEDTOKENRESPONSE._serialized_start=887 | ||||
|   _GRANTEDTOKENRESPONSE._serialized_end=1045 | ||||
|   _CHALLENGESRESPONSE._serialized_start=1047 | ||||
|   _CHALLENGESRESPONSE._serialized_end=1142 | ||||
|   _CLIENTSECRETPARAMETERS._serialized_start=1144 | ||||
|   _CLIENTSECRETPARAMETERS._serialized_end=1182 | ||||
|   _EVALUATEJSPARAMETERS._serialized_start=1184 | ||||
|   _EVALUATEJSPARAMETERS._serialized_end=1239 | ||||
|   _HASHCASHPARAMETERS._serialized_start=1241 | ||||
|   _HASHCASHPARAMETERS._serialized_end=1293 | ||||
|   _CHALLENGE._serialized_start=1296 | ||||
|   _CHALLENGE._serialized_end=1642 | ||||
|   _CLIENTSECRETHMACANSWER._serialized_start=1644 | ||||
|   _CLIENTSECRETHMACANSWER._serialized_end=1682 | ||||
|   _EVALUATEJSANSWER._serialized_start=1684 | ||||
|   _EVALUATEJSANSWER._serialized_end=1718 | ||||
|   _HASHCASHANSWER._serialized_start=1720 | ||||
|   _HASHCASHANSWER._serialized_end=1752 | ||||
|   _CHALLENGEANSWER._serialized_start=1755 | ||||
|   _CHALLENGEANSWER._serialized_end=2063 | ||||
|   _CLIENTTOKENBADREQUEST._serialized_start=2065 | ||||
|   _CLIENTTOKENBADREQUEST._serialized_end=2105 | ||||
| # @@protoc_insertion_point(module_scope) | ||||
							
								
								
									
										2340
									
								
								resources/lib/librespot/proto/Connect_pb2.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										2340
									
								
								resources/lib/librespot/proto/Connect_pb2.py
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										36
									
								
								resources/lib/librespot/proto/Connectivity_pb2.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								resources/lib/librespot/proto/Connectivity_pb2.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,36 @@ | |||
| # -*- coding: utf-8 -*- | ||||
| # Generated by the protocol buffer compiler.  DO NOT EDIT! | ||||
| # source: connectivity.proto | ||||
| """Generated protocol buffer code.""" | ||||
| from google.protobuf.internal import builder as _builder | ||||
| from google.protobuf import descriptor as _descriptor | ||||
| from google.protobuf import descriptor_pool as _descriptor_pool | ||||
| from google.protobuf import symbol_database as _symbol_database | ||||
| # @@protoc_insertion_point(imports) | ||||
| 
 | ||||
| _sym_db = _symbol_database.Default() | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x12\x63onnectivity.proto\x12\x1bspotify.clienttoken.data.v0\"{\n\x13\x43onnectivitySdkData\x12Q\n\x16platform_specific_data\x18\x01 \x01(\x0b\x32\x31.spotify.clienttoken.data.v0.PlatformSpecificData\x12\x11\n\tdevice_id\x18\x02 \x01(\t\"\xdf\x01\n\x14PlatformSpecificData\x12\x41\n\x07\x61ndroid\x18\x01 \x01(\x0b\x32..spotify.clienttoken.data.v0.NativeAndroidDataH\x00\x12\x39\n\x03ios\x18\x02 \x01(\x0b\x32*.spotify.clienttoken.data.v0.NativeIOSDataH\x00\x12\x41\n\x07windows\x18\x04 \x01(\x0b\x32..spotify.clienttoken.data.v0.NativeWindowsDataH\x00\x42\x06\n\x04\x64\x61ta\"\xb9\x01\n\x11NativeAndroidData\x12\x19\n\x11major_sdk_version\x18\x01 \x01(\x05\x12\x19\n\x11minor_sdk_version\x18\x02 \x01(\x05\x12\x19\n\x11patch_sdk_version\x18\x03 \x01(\x05\x12\x13\n\x0b\x61pi_version\x18\x04 \x01(\r\x12>\n\x11screen_dimensions\x18\x05 \x01(\x0b\x32#.spotify.clienttoken.data.v0.Screen\"\x9e\x01\n\rNativeIOSData\x12\x1c\n\x14user_interface_idiom\x18\x01 \x01(\x05\x12\x1f\n\x17target_iphone_simulator\x18\x02 \x01(\x08\x12\x12\n\nhw_machine\x18\x03 \x01(\t\x12\x16\n\x0esystem_version\x18\x04 \x01(\t\x12\"\n\x1asimulator_model_identifier\x18\x05 \x01(\t\"\xa0\x01\n\x11NativeWindowsData\x12\x12\n\nsomething1\x18\x01 \x01(\x05\x12\x12\n\nsomething3\x18\x03 \x01(\x05\x12\x12\n\nsomething4\x18\x04 \x01(\x05\x12\x12\n\nsomething6\x18\x06 \x01(\x05\x12\x12\n\nsomething7\x18\x07 \x01(\x05\x12\x12\n\nsomething8\x18\x08 \x01(\x05\x12\x13\n\x0bsomething10\x18\n \x01(\x08\"8\n\x06Screen\x12\r\n\x05width\x18\x01 \x01(\x05\x12\x0e\n\x06height\x18\x02 \x01(\x05\x12\x0f\n\x07\x64\x65nsity\x18\x03 \x01(\x05\x42#\n\x1f\x63om.spotify.clienttoken.data.v0H\x02\x62\x06proto3') | ||||
| 
 | ||||
| _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) | ||||
| _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'connectivity_pb2', globals()) | ||||
| if _descriptor._USE_C_DESCRIPTORS == False: | ||||
| 
 | ||||
|   DESCRIPTOR._options = None | ||||
|   DESCRIPTOR._serialized_options = b'\n\037com.spotify.clienttoken.data.v0H\002' | ||||
|   _CONNECTIVITYSDKDATA._serialized_start=51 | ||||
|   _CONNECTIVITYSDKDATA._serialized_end=174 | ||||
|   _PLATFORMSPECIFICDATA._serialized_start=177 | ||||
|   _PLATFORMSPECIFICDATA._serialized_end=400 | ||||
|   _NATIVEANDROIDDATA._serialized_start=403 | ||||
|   _NATIVEANDROIDDATA._serialized_end=588 | ||||
|   _NATIVEIOSDATA._serialized_start=591 | ||||
|   _NATIVEIOSDATA._serialized_end=749 | ||||
|   _NATIVEWINDOWSDATA._serialized_start=752 | ||||
|   _NATIVEWINDOWSDATA._serialized_end=912 | ||||
|   _SCREEN._serialized_start=914 | ||||
|   _SCREEN._serialized_end=970 | ||||
| # @@protoc_insertion_point(module_scope) | ||||
							
								
								
									
										239
									
								
								resources/lib/librespot/proto/ContextPage_pb2.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										239
									
								
								resources/lib/librespot/proto/ContextPage_pb2.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,239 @@ | |||
| # -*- coding: utf-8 -*- | ||||
| # Generated by the protocol buffer compiler.  DO NOT EDIT! | ||||
| # source: context_page.proto | ||||
| """Generated protocol buffer code.""" | ||||
| import ContextTrack_pb2 as context__track__pb2 | ||||
| from google.protobuf import descriptor as _descriptor | ||||
| from google.protobuf import message as _message | ||||
| from google.protobuf import reflection as _reflection | ||||
| from google.protobuf import symbol_database as _symbol_database | ||||
| 
 | ||||
| # @@protoc_insertion_point(imports) | ||||
| 
 | ||||
| _sym_db = _symbol_database.Default() | ||||
| 
 | ||||
| DESCRIPTOR = _descriptor.FileDescriptor( | ||||
|     name="context_page.proto", | ||||
|     package="spotify.player.proto", | ||||
|     syntax="proto2", | ||||
|     serialized_options=b"\n\023com.spotify.contextH\002", | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     serialized_pb= | ||||
|     b'\n\x12\x63ontext_page.proto\x12\x14spotify.player.proto\x1a\x13\x63ontext_track.proto"\xef\x01\n\x0b\x43ontextPage\x12\x10\n\x08page_url\x18\x01 \x01(\t\x12\x15\n\rnext_page_url\x18\x02 \x01(\t\x12\x41\n\x08metadata\x18\x03 \x03(\x0b\x32/.spotify.player.proto.ContextPage.MetadataEntry\x12\x32\n\x06tracks\x18\x04 \x03(\x0b\x32".spotify.player.proto.ContextTrack\x12\x0f\n\x07loading\x18\x05 \x01(\x08\x1a/\n\rMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\x17\n\x13\x63om.spotify.contextH\x02', | ||||
|     dependencies=[ | ||||
|         context__track__pb2.DESCRIPTOR, | ||||
|     ], | ||||
| ) | ||||
| 
 | ||||
| _CONTEXTPAGE_METADATAENTRY = _descriptor.Descriptor( | ||||
|     name="MetadataEntry", | ||||
|     full_name="spotify.player.proto.ContextPage.MetadataEntry", | ||||
|     filename=None, | ||||
|     file=DESCRIPTOR, | ||||
|     containing_type=None, | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     fields=[ | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="key", | ||||
|             full_name="spotify.player.proto.ContextPage.MetadataEntry.key", | ||||
|             index=0, | ||||
|             number=1, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"".decode("utf-8"), | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="value", | ||||
|             full_name="spotify.player.proto.ContextPage.MetadataEntry.value", | ||||
|             index=1, | ||||
|             number=2, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"".decode("utf-8"), | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|     ], | ||||
|     extensions=[], | ||||
|     nested_types=[], | ||||
|     enum_types=[], | ||||
|     serialized_options=b"8\001", | ||||
|     is_extendable=False, | ||||
|     syntax="proto2", | ||||
|     extension_ranges=[], | ||||
|     oneofs=[], | ||||
|     serialized_start=258, | ||||
|     serialized_end=305, | ||||
| ) | ||||
| 
 | ||||
| _CONTEXTPAGE = _descriptor.Descriptor( | ||||
|     name="ContextPage", | ||||
|     full_name="spotify.player.proto.ContextPage", | ||||
|     filename=None, | ||||
|     file=DESCRIPTOR, | ||||
|     containing_type=None, | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     fields=[ | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="page_url", | ||||
|             full_name="spotify.player.proto.ContextPage.page_url", | ||||
|             index=0, | ||||
|             number=1, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"".decode("utf-8"), | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="next_page_url", | ||||
|             full_name="spotify.player.proto.ContextPage.next_page_url", | ||||
|             index=1, | ||||
|             number=2, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"".decode("utf-8"), | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="metadata", | ||||
|             full_name="spotify.player.proto.ContextPage.metadata", | ||||
|             index=2, | ||||
|             number=3, | ||||
|             type=11, | ||||
|             cpp_type=10, | ||||
|             label=3, | ||||
|             has_default_value=False, | ||||
|             default_value=[], | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="tracks", | ||||
|             full_name="spotify.player.proto.ContextPage.tracks", | ||||
|             index=3, | ||||
|             number=4, | ||||
|             type=11, | ||||
|             cpp_type=10, | ||||
|             label=3, | ||||
|             has_default_value=False, | ||||
|             default_value=[], | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="loading", | ||||
|             full_name="spotify.player.proto.ContextPage.loading", | ||||
|             index=4, | ||||
|             number=5, | ||||
|             type=8, | ||||
|             cpp_type=7, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=False, | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|     ], | ||||
|     extensions=[], | ||||
|     nested_types=[ | ||||
|         _CONTEXTPAGE_METADATAENTRY, | ||||
|     ], | ||||
|     enum_types=[], | ||||
|     serialized_options=None, | ||||
|     is_extendable=False, | ||||
|     syntax="proto2", | ||||
|     extension_ranges=[], | ||||
|     oneofs=[], | ||||
|     serialized_start=66, | ||||
|     serialized_end=305, | ||||
| ) | ||||
| 
 | ||||
| _CONTEXTPAGE_METADATAENTRY.containing_type = _CONTEXTPAGE | ||||
| _CONTEXTPAGE.fields_by_name[ | ||||
|     "metadata"].message_type = _CONTEXTPAGE_METADATAENTRY | ||||
| _CONTEXTPAGE.fields_by_name[ | ||||
|     "tracks"].message_type = context__track__pb2._CONTEXTTRACK | ||||
| DESCRIPTOR.message_types_by_name["ContextPage"] = _CONTEXTPAGE | ||||
| _sym_db.RegisterFileDescriptor(DESCRIPTOR) | ||||
| 
 | ||||
| ContextPage = _reflection.GeneratedProtocolMessageType( | ||||
|     "ContextPage", | ||||
|     (_message.Message, ), | ||||
|     { | ||||
|         "MetadataEntry": | ||||
|         _reflection.GeneratedProtocolMessageType( | ||||
|             "MetadataEntry", | ||||
|             (_message.Message, ), | ||||
|             { | ||||
|                 "DESCRIPTOR": _CONTEXTPAGE_METADATAENTRY, | ||||
|                 "__module__": "context_page_pb2" | ||||
|                 # @@protoc_insertion_point(class_scope:spotify.player.proto.ContextPage.MetadataEntry) | ||||
|             }, | ||||
|         ), | ||||
|         "DESCRIPTOR": | ||||
|         _CONTEXTPAGE, | ||||
|         "__module__": | ||||
|         "context_page_pb2" | ||||
|         # @@protoc_insertion_point(class_scope:spotify.player.proto.ContextPage) | ||||
|     }, | ||||
| ) | ||||
| _sym_db.RegisterMessage(ContextPage) | ||||
| _sym_db.RegisterMessage(ContextPage.MetadataEntry) | ||||
| 
 | ||||
| DESCRIPTOR._options = None | ||||
| _CONTEXTPAGE_METADATAENTRY._options = None | ||||
| # @@protoc_insertion_point(module_scope) | ||||
							
								
								
									
										215
									
								
								resources/lib/librespot/proto/ContextPlayerOptions_pb2.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										215
									
								
								resources/lib/librespot/proto/ContextPlayerOptions_pb2.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,215 @@ | |||
| # -*- coding: utf-8 -*- | ||||
| # Generated by the protocol buffer compiler.  DO NOT EDIT! | ||||
| # source: context_player_options.proto | ||||
| """Generated protocol buffer code.""" | ||||
| from google.protobuf import descriptor as _descriptor | ||||
| from google.protobuf import message as _message | ||||
| from google.protobuf import reflection as _reflection | ||||
| from google.protobuf import symbol_database as _symbol_database | ||||
| 
 | ||||
| # @@protoc_insertion_point(imports) | ||||
| 
 | ||||
| _sym_db = _symbol_database.Default() | ||||
| 
 | ||||
| DESCRIPTOR = _descriptor.FileDescriptor( | ||||
|     name="context_player_options.proto", | ||||
|     package="spotify.player.proto", | ||||
|     syntax="proto2", | ||||
|     serialized_options=b"\n\023com.spotify.contextH\002", | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     serialized_pb= | ||||
|     b'\n\x1c\x63ontext_player_options.proto\x12\x14spotify.player.proto"e\n\x14\x43ontextPlayerOptions\x12\x19\n\x11shuffling_context\x18\x01 \x01(\x08\x12\x19\n\x11repeating_context\x18\x02 \x01(\x08\x12\x17\n\x0frepeating_track\x18\x03 \x01(\x08"m\n\x1c\x43ontextPlayerOptionOverrides\x12\x19\n\x11shuffling_context\x18\x01 \x01(\x08\x12\x19\n\x11repeating_context\x18\x02 \x01(\x08\x12\x17\n\x0frepeating_track\x18\x03 \x01(\x08\x42\x17\n\x13\x63om.spotify.contextH\x02', | ||||
| ) | ||||
| 
 | ||||
| _CONTEXTPLAYEROPTIONS = _descriptor.Descriptor( | ||||
|     name="ContextPlayerOptions", | ||||
|     full_name="spotify.player.proto.ContextPlayerOptions", | ||||
|     filename=None, | ||||
|     file=DESCRIPTOR, | ||||
|     containing_type=None, | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     fields=[ | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="shuffling_context", | ||||
|             full_name= | ||||
|             "spotify.player.proto.ContextPlayerOptions.shuffling_context", | ||||
|             index=0, | ||||
|             number=1, | ||||
|             type=8, | ||||
|             cpp_type=7, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=False, | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="repeating_context", | ||||
|             full_name= | ||||
|             "spotify.player.proto.ContextPlayerOptions.repeating_context", | ||||
|             index=1, | ||||
|             number=2, | ||||
|             type=8, | ||||
|             cpp_type=7, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=False, | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="repeating_track", | ||||
|             full_name= | ||||
|             "spotify.player.proto.ContextPlayerOptions.repeating_track", | ||||
|             index=2, | ||||
|             number=3, | ||||
|             type=8, | ||||
|             cpp_type=7, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=False, | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|     ], | ||||
|     extensions=[], | ||||
|     nested_types=[], | ||||
|     enum_types=[], | ||||
|     serialized_options=None, | ||||
|     is_extendable=False, | ||||
|     syntax="proto2", | ||||
|     extension_ranges=[], | ||||
|     oneofs=[], | ||||
|     serialized_start=54, | ||||
|     serialized_end=155, | ||||
| ) | ||||
| 
 | ||||
| _CONTEXTPLAYEROPTIONOVERRIDES = _descriptor.Descriptor( | ||||
|     name="ContextPlayerOptionOverrides", | ||||
|     full_name="spotify.player.proto.ContextPlayerOptionOverrides", | ||||
|     filename=None, | ||||
|     file=DESCRIPTOR, | ||||
|     containing_type=None, | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     fields=[ | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="shuffling_context", | ||||
|             full_name= | ||||
|             "spotify.player.proto.ContextPlayerOptionOverrides.shuffling_context", | ||||
|             index=0, | ||||
|             number=1, | ||||
|             type=8, | ||||
|             cpp_type=7, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=False, | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="repeating_context", | ||||
|             full_name= | ||||
|             "spotify.player.proto.ContextPlayerOptionOverrides.repeating_context", | ||||
|             index=1, | ||||
|             number=2, | ||||
|             type=8, | ||||
|             cpp_type=7, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=False, | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="repeating_track", | ||||
|             full_name= | ||||
|             "spotify.player.proto.ContextPlayerOptionOverrides.repeating_track", | ||||
|             index=2, | ||||
|             number=3, | ||||
|             type=8, | ||||
|             cpp_type=7, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=False, | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|     ], | ||||
|     extensions=[], | ||||
|     nested_types=[], | ||||
|     enum_types=[], | ||||
|     serialized_options=None, | ||||
|     is_extendable=False, | ||||
|     syntax="proto2", | ||||
|     extension_ranges=[], | ||||
|     oneofs=[], | ||||
|     serialized_start=157, | ||||
|     serialized_end=266, | ||||
| ) | ||||
| 
 | ||||
| DESCRIPTOR.message_types_by_name[ | ||||
|     "ContextPlayerOptions"] = _CONTEXTPLAYEROPTIONS | ||||
| DESCRIPTOR.message_types_by_name[ | ||||
|     "ContextPlayerOptionOverrides"] = _CONTEXTPLAYEROPTIONOVERRIDES | ||||
| _sym_db.RegisterFileDescriptor(DESCRIPTOR) | ||||
| 
 | ||||
| ContextPlayerOptions = _reflection.GeneratedProtocolMessageType( | ||||
|     "ContextPlayerOptions", | ||||
|     (_message.Message, ), | ||||
|     { | ||||
|         "DESCRIPTOR": _CONTEXTPLAYEROPTIONS, | ||||
|         "__module__": "context_player_options_pb2" | ||||
|         # @@protoc_insertion_point(class_scope:spotify.player.proto.ContextPlayerOptions) | ||||
|     }, | ||||
| ) | ||||
| _sym_db.RegisterMessage(ContextPlayerOptions) | ||||
| 
 | ||||
| ContextPlayerOptionOverrides = _reflection.GeneratedProtocolMessageType( | ||||
|     "ContextPlayerOptionOverrides", | ||||
|     (_message.Message, ), | ||||
|     { | ||||
|         "DESCRIPTOR": _CONTEXTPLAYEROPTIONOVERRIDES, | ||||
|         "__module__": "context_player_options_pb2" | ||||
|         # @@protoc_insertion_point(class_scope:spotify.player.proto.ContextPlayerOptionOverrides) | ||||
|     }, | ||||
| ) | ||||
| _sym_db.RegisterMessage(ContextPlayerOptionOverrides) | ||||
| 
 | ||||
| DESCRIPTOR._options = None | ||||
| # @@protoc_insertion_point(module_scope) | ||||
							
								
								
									
										214
									
								
								resources/lib/librespot/proto/ContextTrack_pb2.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										214
									
								
								resources/lib/librespot/proto/ContextTrack_pb2.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,214 @@ | |||
| # -*- coding: utf-8 -*- | ||||
| # Generated by the protocol buffer compiler.  DO NOT EDIT! | ||||
| # source: context_track.proto | ||||
| """Generated protocol buffer code.""" | ||||
| from google.protobuf import descriptor as _descriptor | ||||
| from google.protobuf import message as _message | ||||
| from google.protobuf import reflection as _reflection | ||||
| from google.protobuf import symbol_database as _symbol_database | ||||
| 
 | ||||
| # @@protoc_insertion_point(imports) | ||||
| 
 | ||||
| _sym_db = _symbol_database.Default() | ||||
| 
 | ||||
| DESCRIPTOR = _descriptor.FileDescriptor( | ||||
|     name="context_track.proto", | ||||
|     package="spotify.player.proto", | ||||
|     syntax="proto2", | ||||
|     serialized_options=b"\n\023com.spotify.contextH\002", | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     serialized_pb= | ||||
|     b'\n\x13\x63ontext_track.proto\x12\x14spotify.player.proto"\xaa\x01\n\x0c\x43ontextTrack\x12\x0b\n\x03uri\x18\x01 \x01(\t\x12\x0b\n\x03uid\x18\x02 \x01(\t\x12\x0b\n\x03gid\x18\x03 \x01(\x0c\x12\x42\n\x08metadata\x18\x04 \x03(\x0b\x32\x30.spotify.player.proto.ContextTrack.MetadataEntry\x1a/\n\rMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\x17\n\x13\x63om.spotify.contextH\x02', | ||||
| ) | ||||
| 
 | ||||
| _CONTEXTTRACK_METADATAENTRY = _descriptor.Descriptor( | ||||
|     name="MetadataEntry", | ||||
|     full_name="spotify.player.proto.ContextTrack.MetadataEntry", | ||||
|     filename=None, | ||||
|     file=DESCRIPTOR, | ||||
|     containing_type=None, | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     fields=[ | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="key", | ||||
|             full_name="spotify.player.proto.ContextTrack.MetadataEntry.key", | ||||
|             index=0, | ||||
|             number=1, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"".decode("utf-8"), | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="value", | ||||
|             full_name="spotify.player.proto.ContextTrack.MetadataEntry.value", | ||||
|             index=1, | ||||
|             number=2, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"".decode("utf-8"), | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|     ], | ||||
|     extensions=[], | ||||
|     nested_types=[], | ||||
|     enum_types=[], | ||||
|     serialized_options=b"8\001", | ||||
|     is_extendable=False, | ||||
|     syntax="proto2", | ||||
|     extension_ranges=[], | ||||
|     oneofs=[], | ||||
|     serialized_start=169, | ||||
|     serialized_end=216, | ||||
| ) | ||||
| 
 | ||||
| _CONTEXTTRACK = _descriptor.Descriptor( | ||||
|     name="ContextTrack", | ||||
|     full_name="spotify.player.proto.ContextTrack", | ||||
|     filename=None, | ||||
|     file=DESCRIPTOR, | ||||
|     containing_type=None, | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     fields=[ | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="uri", | ||||
|             full_name="spotify.player.proto.ContextTrack.uri", | ||||
|             index=0, | ||||
|             number=1, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"".decode("utf-8"), | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="uid", | ||||
|             full_name="spotify.player.proto.ContextTrack.uid", | ||||
|             index=1, | ||||
|             number=2, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"".decode("utf-8"), | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="gid", | ||||
|             full_name="spotify.player.proto.ContextTrack.gid", | ||||
|             index=2, | ||||
|             number=3, | ||||
|             type=12, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"", | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="metadata", | ||||
|             full_name="spotify.player.proto.ContextTrack.metadata", | ||||
|             index=3, | ||||
|             number=4, | ||||
|             type=11, | ||||
|             cpp_type=10, | ||||
|             label=3, | ||||
|             has_default_value=False, | ||||
|             default_value=[], | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|     ], | ||||
|     extensions=[], | ||||
|     nested_types=[ | ||||
|         _CONTEXTTRACK_METADATAENTRY, | ||||
|     ], | ||||
|     enum_types=[], | ||||
|     serialized_options=None, | ||||
|     is_extendable=False, | ||||
|     syntax="proto2", | ||||
|     extension_ranges=[], | ||||
|     oneofs=[], | ||||
|     serialized_start=46, | ||||
|     serialized_end=216, | ||||
| ) | ||||
| 
 | ||||
| _CONTEXTTRACK_METADATAENTRY.containing_type = _CONTEXTTRACK | ||||
| _CONTEXTTRACK.fields_by_name[ | ||||
|     "metadata"].message_type = _CONTEXTTRACK_METADATAENTRY | ||||
| DESCRIPTOR.message_types_by_name["ContextTrack"] = _CONTEXTTRACK | ||||
| _sym_db.RegisterFileDescriptor(DESCRIPTOR) | ||||
| 
 | ||||
| ContextTrack = _reflection.GeneratedProtocolMessageType( | ||||
|     "ContextTrack", | ||||
|     (_message.Message, ), | ||||
|     { | ||||
|         "MetadataEntry": | ||||
|         _reflection.GeneratedProtocolMessageType( | ||||
|             "MetadataEntry", | ||||
|             (_message.Message, ), | ||||
|             { | ||||
|                 "DESCRIPTOR": _CONTEXTTRACK_METADATAENTRY, | ||||
|                 "__module__": "context_track_pb2" | ||||
|                 # @@protoc_insertion_point(class_scope:spotify.player.proto.ContextTrack.MetadataEntry) | ||||
|             }, | ||||
|         ), | ||||
|         "DESCRIPTOR": | ||||
|         _CONTEXTTRACK, | ||||
|         "__module__": | ||||
|         "context_track_pb2" | ||||
|         # @@protoc_insertion_point(class_scope:spotify.player.proto.ContextTrack) | ||||
|     }, | ||||
| ) | ||||
| _sym_db.RegisterMessage(ContextTrack) | ||||
| _sym_db.RegisterMessage(ContextTrack.MetadataEntry) | ||||
| 
 | ||||
| DESCRIPTOR._options = None | ||||
| _CONTEXTTRACK_METADATAENTRY._options = None | ||||
| # @@protoc_insertion_point(module_scope) | ||||
							
								
								
									
										260
									
								
								resources/lib/librespot/proto/Context_pb2.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										260
									
								
								resources/lib/librespot/proto/Context_pb2.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,260 @@ | |||
| # -*- coding: utf-8 -*- | ||||
| # Generated by the protocol buffer compiler.  DO NOT EDIT! | ||||
| # source: context.proto | ||||
| """Generated protocol buffer code.""" | ||||
| import ContextPage_pb2 as context__page__pb2 | ||||
| import Restrictions_pb2 as restrictions__pb2 | ||||
| from google.protobuf import descriptor as _descriptor | ||||
| from google.protobuf import message as _message | ||||
| from google.protobuf import reflection as _reflection | ||||
| from google.protobuf import symbol_database as _symbol_database | ||||
| 
 | ||||
| # @@protoc_insertion_point(imports) | ||||
| 
 | ||||
| _sym_db = _symbol_database.Default() | ||||
| 
 | ||||
| DESCRIPTOR = _descriptor.FileDescriptor( | ||||
|     name="context.proto", | ||||
|     package="spotify.player.proto", | ||||
|     syntax="proto2", | ||||
|     serialized_options=b"\n\023com.spotify.contextH\002", | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     serialized_pb= | ||||
|     b'\n\rcontext.proto\x12\x14spotify.player.proto\x1a\x12\x63ontext_page.proto\x1a\x12restrictions.proto"\x90\x02\n\x07\x43ontext\x12\x0b\n\x03uri\x18\x01 \x01(\t\x12\x0b\n\x03url\x18\x02 \x01(\t\x12=\n\x08metadata\x18\x03 \x03(\x0b\x32+.spotify.player.proto.Context.MetadataEntry\x12\x38\n\x0crestrictions\x18\x04 \x01(\x0b\x32".spotify.player.proto.Restrictions\x12\x30\n\x05pages\x18\x05 \x03(\x0b\x32!.spotify.player.proto.ContextPage\x12\x0f\n\x07loading\x18\x06 \x01(\x08\x1a/\n\rMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\x17\n\x13\x63om.spotify.contextH\x02', | ||||
|     dependencies=[ | ||||
|         context__page__pb2.DESCRIPTOR, | ||||
|         restrictions__pb2.DESCRIPTOR, | ||||
|     ], | ||||
| ) | ||||
| 
 | ||||
| _CONTEXT_METADATAENTRY = _descriptor.Descriptor( | ||||
|     name="MetadataEntry", | ||||
|     full_name="spotify.player.proto.Context.MetadataEntry", | ||||
|     filename=None, | ||||
|     file=DESCRIPTOR, | ||||
|     containing_type=None, | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     fields=[ | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="key", | ||||
|             full_name="spotify.player.proto.Context.MetadataEntry.key", | ||||
|             index=0, | ||||
|             number=1, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"".decode("utf-8"), | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="value", | ||||
|             full_name="spotify.player.proto.Context.MetadataEntry.value", | ||||
|             index=1, | ||||
|             number=2, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"".decode("utf-8"), | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|     ], | ||||
|     extensions=[], | ||||
|     nested_types=[], | ||||
|     enum_types=[], | ||||
|     serialized_options=b"8\001", | ||||
|     is_extendable=False, | ||||
|     syntax="proto2", | ||||
|     extension_ranges=[], | ||||
|     oneofs=[], | ||||
|     serialized_start=305, | ||||
|     serialized_end=352, | ||||
| ) | ||||
| 
 | ||||
| _CONTEXT = _descriptor.Descriptor( | ||||
|     name="Context", | ||||
|     full_name="spotify.player.proto.Context", | ||||
|     filename=None, | ||||
|     file=DESCRIPTOR, | ||||
|     containing_type=None, | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     fields=[ | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="uri", | ||||
|             full_name="spotify.player.proto.Context.uri", | ||||
|             index=0, | ||||
|             number=1, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"".decode("utf-8"), | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="url", | ||||
|             full_name="spotify.player.proto.Context.url", | ||||
|             index=1, | ||||
|             number=2, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"".decode("utf-8"), | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="metadata", | ||||
|             full_name="spotify.player.proto.Context.metadata", | ||||
|             index=2, | ||||
|             number=3, | ||||
|             type=11, | ||||
|             cpp_type=10, | ||||
|             label=3, | ||||
|             has_default_value=False, | ||||
|             default_value=[], | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="restrictions", | ||||
|             full_name="spotify.player.proto.Context.restrictions", | ||||
|             index=3, | ||||
|             number=4, | ||||
|             type=11, | ||||
|             cpp_type=10, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=None, | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="pages", | ||||
|             full_name="spotify.player.proto.Context.pages", | ||||
|             index=4, | ||||
|             number=5, | ||||
|             type=11, | ||||
|             cpp_type=10, | ||||
|             label=3, | ||||
|             has_default_value=False, | ||||
|             default_value=[], | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="loading", | ||||
|             full_name="spotify.player.proto.Context.loading", | ||||
|             index=5, | ||||
|             number=6, | ||||
|             type=8, | ||||
|             cpp_type=7, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=False, | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|     ], | ||||
|     extensions=[], | ||||
|     nested_types=[ | ||||
|         _CONTEXT_METADATAENTRY, | ||||
|     ], | ||||
|     enum_types=[], | ||||
|     serialized_options=None, | ||||
|     is_extendable=False, | ||||
|     syntax="proto2", | ||||
|     extension_ranges=[], | ||||
|     oneofs=[], | ||||
|     serialized_start=80, | ||||
|     serialized_end=352, | ||||
| ) | ||||
| 
 | ||||
| _CONTEXT_METADATAENTRY.containing_type = _CONTEXT | ||||
| _CONTEXT.fields_by_name["metadata"].message_type = _CONTEXT_METADATAENTRY | ||||
| _CONTEXT.fields_by_name[ | ||||
|     "restrictions"].message_type = restrictions__pb2._RESTRICTIONS | ||||
| _CONTEXT.fields_by_name["pages"].message_type = context__page__pb2._CONTEXTPAGE | ||||
| DESCRIPTOR.message_types_by_name["Context"] = _CONTEXT | ||||
| _sym_db.RegisterFileDescriptor(DESCRIPTOR) | ||||
| 
 | ||||
| Context = _reflection.GeneratedProtocolMessageType( | ||||
|     "Context", | ||||
|     (_message.Message, ), | ||||
|     { | ||||
|         "MetadataEntry": | ||||
|         _reflection.GeneratedProtocolMessageType( | ||||
|             "MetadataEntry", | ||||
|             (_message.Message, ), | ||||
|             { | ||||
|                 "DESCRIPTOR": _CONTEXT_METADATAENTRY, | ||||
|                 "__module__": "context_pb2" | ||||
|                 # @@protoc_insertion_point(class_scope:spotify.player.proto.Context.MetadataEntry) | ||||
|             }, | ||||
|         ), | ||||
|         "DESCRIPTOR": | ||||
|         _CONTEXT, | ||||
|         "__module__": | ||||
|         "context_pb2" | ||||
|         # @@protoc_insertion_point(class_scope:spotify.player.proto.Context) | ||||
|     }, | ||||
| ) | ||||
| _sym_db.RegisterMessage(Context) | ||||
| _sym_db.RegisterMessage(Context.MetadataEntry) | ||||
| 
 | ||||
| DESCRIPTOR._options = None | ||||
| _CONTEXT_METADATAENTRY._options = None | ||||
| # @@protoc_insertion_point(module_scope) | ||||
							
								
								
									
										147
									
								
								resources/lib/librespot/proto/ExplicitContentPubsub_pb2.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										147
									
								
								resources/lib/librespot/proto/ExplicitContentPubsub_pb2.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,147 @@ | |||
| # -*- coding: utf-8 -*- | ||||
| # Generated by the protocol buffer compiler.  DO NOT EDIT! | ||||
| # source: explicit_content_pubsub.proto | ||||
| """Generated protocol buffer code.""" | ||||
| from google.protobuf import descriptor as _descriptor | ||||
| from google.protobuf import message as _message | ||||
| from google.protobuf import reflection as _reflection | ||||
| from google.protobuf import symbol_database as _symbol_database | ||||
| # @@protoc_insertion_point(imports) | ||||
| 
 | ||||
| _sym_db = _symbol_database.Default() | ||||
| 
 | ||||
| DESCRIPTOR = _descriptor.FileDescriptor( | ||||
|     name='explicit_content_pubsub.proto', | ||||
|     package='spotify.explicit_content.proto', | ||||
|     syntax='proto2', | ||||
|     serialized_options=b'\n\024com.spotify.explicitH\002', | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     serialized_pb= | ||||
|     b'\n\x1d\x65xplicit_content_pubsub.proto\x12\x1espotify.explicit_content.proto\"*\n\x0cKeyValuePair\x12\x0b\n\x03key\x18\x01 \x02(\t\x12\r\n\x05value\x18\x02 \x02(\t\"S\n\x14UserAttributesUpdate\x12;\n\x05pairs\x18\x01 \x03(\x0b\x32,.spotify.explicit_content.proto.KeyValuePairB\x18\n\x14\x63om.spotify.explicitH\x02' | ||||
| ) | ||||
| 
 | ||||
| _KEYVALUEPAIR = _descriptor.Descriptor( | ||||
|     name='KeyValuePair', | ||||
|     full_name='spotify.explicit_content.proto.KeyValuePair', | ||||
|     filename=None, | ||||
|     file=DESCRIPTOR, | ||||
|     containing_type=None, | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     fields=[ | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name='key', | ||||
|             full_name='spotify.explicit_content.proto.KeyValuePair.key', | ||||
|             index=0, | ||||
|             number=1, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=2, | ||||
|             has_default_value=False, | ||||
|             default_value=b"".decode('utf-8'), | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name='value', | ||||
|             full_name='spotify.explicit_content.proto.KeyValuePair.value', | ||||
|             index=1, | ||||
|             number=2, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=2, | ||||
|             has_default_value=False, | ||||
|             default_value=b"".decode('utf-8'), | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key), | ||||
|     ], | ||||
|     extensions=[], | ||||
|     nested_types=[], | ||||
|     enum_types=[], | ||||
|     serialized_options=None, | ||||
|     is_extendable=False, | ||||
|     syntax='proto2', | ||||
|     extension_ranges=[], | ||||
|     oneofs=[], | ||||
|     serialized_start=65, | ||||
|     serialized_end=107, | ||||
| ) | ||||
| 
 | ||||
| _USERATTRIBUTESUPDATE = _descriptor.Descriptor( | ||||
|     name='UserAttributesUpdate', | ||||
|     full_name='spotify.explicit_content.proto.UserAttributesUpdate', | ||||
|     filename=None, | ||||
|     file=DESCRIPTOR, | ||||
|     containing_type=None, | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     fields=[ | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name='pairs', | ||||
|             full_name= | ||||
|             'spotify.explicit_content.proto.UserAttributesUpdate.pairs', | ||||
|             index=0, | ||||
|             number=1, | ||||
|             type=11, | ||||
|             cpp_type=10, | ||||
|             label=3, | ||||
|             has_default_value=False, | ||||
|             default_value=[], | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key), | ||||
|     ], | ||||
|     extensions=[], | ||||
|     nested_types=[], | ||||
|     enum_types=[], | ||||
|     serialized_options=None, | ||||
|     is_extendable=False, | ||||
|     syntax='proto2', | ||||
|     extension_ranges=[], | ||||
|     oneofs=[], | ||||
|     serialized_start=109, | ||||
|     serialized_end=192, | ||||
| ) | ||||
| 
 | ||||
| _USERATTRIBUTESUPDATE.fields_by_name['pairs'].message_type = _KEYVALUEPAIR | ||||
| DESCRIPTOR.message_types_by_name['KeyValuePair'] = _KEYVALUEPAIR | ||||
| DESCRIPTOR.message_types_by_name[ | ||||
|     'UserAttributesUpdate'] = _USERATTRIBUTESUPDATE | ||||
| _sym_db.RegisterFileDescriptor(DESCRIPTOR) | ||||
| 
 | ||||
| KeyValuePair = _reflection.GeneratedProtocolMessageType( | ||||
|     'KeyValuePair', | ||||
|     (_message.Message, ), | ||||
|     { | ||||
|         'DESCRIPTOR': _KEYVALUEPAIR, | ||||
|         '__module__': 'explicit_content_pubsub_pb2' | ||||
|         # @@protoc_insertion_point(class_scope:spotify.explicit_content.proto.KeyValuePair) | ||||
|     }) | ||||
| _sym_db.RegisterMessage(KeyValuePair) | ||||
| 
 | ||||
| UserAttributesUpdate = _reflection.GeneratedProtocolMessageType( | ||||
|     'UserAttributesUpdate', | ||||
|     (_message.Message, ), | ||||
|     { | ||||
|         'DESCRIPTOR': _USERATTRIBUTESUPDATE, | ||||
|         '__module__': 'explicit_content_pubsub_pb2' | ||||
|         # @@protoc_insertion_point(class_scope:spotify.explicit_content.proto.UserAttributesUpdate) | ||||
|     }) | ||||
| _sym_db.RegisterMessage(UserAttributesUpdate) | ||||
| 
 | ||||
| DESCRIPTOR._options = None | ||||
| # @@protoc_insertion_point(module_scope) | ||||
							
								
								
									
										2497
									
								
								resources/lib/librespot/proto/Keyexchange_pb2.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										2497
									
								
								resources/lib/librespot/proto/Keyexchange_pb2.py
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										625
									
								
								resources/lib/librespot/proto/Mercury_pb2.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										625
									
								
								resources/lib/librespot/proto/Mercury_pb2.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,625 @@ | |||
| # -*- coding: utf-8 -*- | ||||
| # Generated by the protocol buffer compiler.  DO NOT EDIT! | ||||
| # source: mercury.proto | ||||
| """Generated protocol buffer code.""" | ||||
| from google.protobuf import descriptor as _descriptor | ||||
| from google.protobuf import message as _message | ||||
| from google.protobuf import reflection as _reflection | ||||
| from google.protobuf import symbol_database as _symbol_database | ||||
| # @@protoc_insertion_point(imports) | ||||
| 
 | ||||
| _sym_db = _symbol_database.Default() | ||||
| 
 | ||||
| DESCRIPTOR = _descriptor.FileDescriptor( | ||||
|     name='mercury.proto', | ||||
|     package='spotify', | ||||
|     syntax='proto2', | ||||
|     serialized_options=b'\n\013com.spotify', | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     serialized_pb= | ||||
|     b'\n\rmercury.proto\x12\x07spotify\"B\n\x16MercuryMultiGetRequest\x12(\n\x07request\x18\x01 \x03(\x0b\x32\x17.spotify.MercuryRequest\"<\n\x14MercuryMultiGetReply\x12$\n\x05reply\x18\x01 \x03(\x0b\x32\x15.spotify.MercuryReply\"O\n\x0eMercuryRequest\x12\x0b\n\x03uri\x18\x01 \x01(\t\x12\x14\n\x0c\x63ontent_type\x18\x02 \x01(\t\x12\x0c\n\x04\x62ody\x18\x03 \x01(\x0c\x12\x0c\n\x04\x65tag\x18\x04 \x01(\x0c\"\xf5\x01\n\x0cMercuryReply\x12\x13\n\x0bstatus_code\x18\x01 \x01(\x11\x12\x16\n\x0estatus_message\x18\x02 \x01(\t\x12\x37\n\x0c\x63\x61\x63he_policy\x18\x03 \x01(\x0e\x32!.spotify.MercuryReply.CachePolicy\x12\x0b\n\x03ttl\x18\x04 \x01(\x11\x12\x0c\n\x04\x65tag\x18\x05 \x01(\x0c\x12\x14\n\x0c\x63ontent_type\x18\x06 \x01(\t\x12\x0c\n\x04\x62ody\x18\x07 \x01(\x0c\"@\n\x0b\x43\x61\x63hePolicy\x12\x0c\n\x08\x43\x41\x43HE_NO\x10\x01\x12\x11\n\rCACHE_PRIVATE\x10\x02\x12\x10\n\x0c\x43\x41\x43HE_PUBLIC\x10\x03\"y\n\x06Header\x12\x0b\n\x03uri\x18\x01 \x01(\t\x12\x14\n\x0c\x63ontent_type\x18\x02 \x01(\t\x12\x0e\n\x06method\x18\x03 \x01(\t\x12\x13\n\x0bstatus_code\x18\x04 \x01(\x11\x12\'\n\x0buser_fields\x18\x06 \x03(\x0b\x32\x12.spotify.UserField\"\'\n\tUserField\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x0c\x42\r\n\x0b\x63om.spotify' | ||||
| ) | ||||
| 
 | ||||
| _MERCURYREPLY_CACHEPOLICY = _descriptor.EnumDescriptor( | ||||
|     name='CachePolicy', | ||||
|     full_name='spotify.MercuryReply.CachePolicy', | ||||
|     filename=None, | ||||
|     file=DESCRIPTOR, | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     values=[ | ||||
|         _descriptor.EnumValueDescriptor( | ||||
|             name='CACHE_NO', | ||||
|             index=0, | ||||
|             number=1, | ||||
|             serialized_options=None, | ||||
|             type=None, | ||||
|             create_key=_descriptor._internal_create_key), | ||||
|         _descriptor.EnumValueDescriptor( | ||||
|             name='CACHE_PRIVATE', | ||||
|             index=1, | ||||
|             number=2, | ||||
|             serialized_options=None, | ||||
|             type=None, | ||||
|             create_key=_descriptor._internal_create_key), | ||||
|         _descriptor.EnumValueDescriptor( | ||||
|             name='CACHE_PUBLIC', | ||||
|             index=2, | ||||
|             number=3, | ||||
|             serialized_options=None, | ||||
|             type=None, | ||||
|             create_key=_descriptor._internal_create_key), | ||||
|     ], | ||||
|     containing_type=None, | ||||
|     serialized_options=None, | ||||
|     serialized_start=419, | ||||
|     serialized_end=483, | ||||
| ) | ||||
| _sym_db.RegisterEnumDescriptor(_MERCURYREPLY_CACHEPOLICY) | ||||
| 
 | ||||
| _MERCURYMULTIGETREQUEST = _descriptor.Descriptor( | ||||
|     name='MercuryMultiGetRequest', | ||||
|     full_name='spotify.MercuryMultiGetRequest', | ||||
|     filename=None, | ||||
|     file=DESCRIPTOR, | ||||
|     containing_type=None, | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     fields=[ | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name='request', | ||||
|             full_name='spotify.MercuryMultiGetRequest.request', | ||||
|             index=0, | ||||
|             number=1, | ||||
|             type=11, | ||||
|             cpp_type=10, | ||||
|             label=3, | ||||
|             has_default_value=False, | ||||
|             default_value=[], | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key), | ||||
|     ], | ||||
|     extensions=[], | ||||
|     nested_types=[], | ||||
|     enum_types=[], | ||||
|     serialized_options=None, | ||||
|     is_extendable=False, | ||||
|     syntax='proto2', | ||||
|     extension_ranges=[], | ||||
|     oneofs=[], | ||||
|     serialized_start=26, | ||||
|     serialized_end=92, | ||||
| ) | ||||
| 
 | ||||
| _MERCURYMULTIGETREPLY = _descriptor.Descriptor( | ||||
|     name='MercuryMultiGetReply', | ||||
|     full_name='spotify.MercuryMultiGetReply', | ||||
|     filename=None, | ||||
|     file=DESCRIPTOR, | ||||
|     containing_type=None, | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     fields=[ | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name='reply', | ||||
|             full_name='spotify.MercuryMultiGetReply.reply', | ||||
|             index=0, | ||||
|             number=1, | ||||
|             type=11, | ||||
|             cpp_type=10, | ||||
|             label=3, | ||||
|             has_default_value=False, | ||||
|             default_value=[], | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key), | ||||
|     ], | ||||
|     extensions=[], | ||||
|     nested_types=[], | ||||
|     enum_types=[], | ||||
|     serialized_options=None, | ||||
|     is_extendable=False, | ||||
|     syntax='proto2', | ||||
|     extension_ranges=[], | ||||
|     oneofs=[], | ||||
|     serialized_start=94, | ||||
|     serialized_end=154, | ||||
| ) | ||||
| 
 | ||||
| _MERCURYREQUEST = _descriptor.Descriptor( | ||||
|     name='MercuryRequest', | ||||
|     full_name='spotify.MercuryRequest', | ||||
|     filename=None, | ||||
|     file=DESCRIPTOR, | ||||
|     containing_type=None, | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     fields=[ | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name='uri', | ||||
|             full_name='spotify.MercuryRequest.uri', | ||||
|             index=0, | ||||
|             number=1, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"".decode('utf-8'), | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name='content_type', | ||||
|             full_name='spotify.MercuryRequest.content_type', | ||||
|             index=1, | ||||
|             number=2, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"".decode('utf-8'), | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name='body', | ||||
|             full_name='spotify.MercuryRequest.body', | ||||
|             index=2, | ||||
|             number=3, | ||||
|             type=12, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"", | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name='etag', | ||||
|             full_name='spotify.MercuryRequest.etag', | ||||
|             index=3, | ||||
|             number=4, | ||||
|             type=12, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"", | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key), | ||||
|     ], | ||||
|     extensions=[], | ||||
|     nested_types=[], | ||||
|     enum_types=[], | ||||
|     serialized_options=None, | ||||
|     is_extendable=False, | ||||
|     syntax='proto2', | ||||
|     extension_ranges=[], | ||||
|     oneofs=[], | ||||
|     serialized_start=156, | ||||
|     serialized_end=235, | ||||
| ) | ||||
| 
 | ||||
| _MERCURYREPLY = _descriptor.Descriptor( | ||||
|     name='MercuryReply', | ||||
|     full_name='spotify.MercuryReply', | ||||
|     filename=None, | ||||
|     file=DESCRIPTOR, | ||||
|     containing_type=None, | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     fields=[ | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name='status_code', | ||||
|             full_name='spotify.MercuryReply.status_code', | ||||
|             index=0, | ||||
|             number=1, | ||||
|             type=17, | ||||
|             cpp_type=1, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=0, | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name='status_message', | ||||
|             full_name='spotify.MercuryReply.status_message', | ||||
|             index=1, | ||||
|             number=2, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"".decode('utf-8'), | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name='cache_policy', | ||||
|             full_name='spotify.MercuryReply.cache_policy', | ||||
|             index=2, | ||||
|             number=3, | ||||
|             type=14, | ||||
|             cpp_type=8, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=1, | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name='ttl', | ||||
|             full_name='spotify.MercuryReply.ttl', | ||||
|             index=3, | ||||
|             number=4, | ||||
|             type=17, | ||||
|             cpp_type=1, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=0, | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name='etag', | ||||
|             full_name='spotify.MercuryReply.etag', | ||||
|             index=4, | ||||
|             number=5, | ||||
|             type=12, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"", | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name='content_type', | ||||
|             full_name='spotify.MercuryReply.content_type', | ||||
|             index=5, | ||||
|             number=6, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"".decode('utf-8'), | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name='body', | ||||
|             full_name='spotify.MercuryReply.body', | ||||
|             index=6, | ||||
|             number=7, | ||||
|             type=12, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"", | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key), | ||||
|     ], | ||||
|     extensions=[], | ||||
|     nested_types=[], | ||||
|     enum_types=[ | ||||
|         _MERCURYREPLY_CACHEPOLICY, | ||||
|     ], | ||||
|     serialized_options=None, | ||||
|     is_extendable=False, | ||||
|     syntax='proto2', | ||||
|     extension_ranges=[], | ||||
|     oneofs=[], | ||||
|     serialized_start=238, | ||||
|     serialized_end=483, | ||||
| ) | ||||
| 
 | ||||
| _HEADER = _descriptor.Descriptor( | ||||
|     name='Header', | ||||
|     full_name='spotify.Header', | ||||
|     filename=None, | ||||
|     file=DESCRIPTOR, | ||||
|     containing_type=None, | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     fields=[ | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name='uri', | ||||
|             full_name='spotify.Header.uri', | ||||
|             index=0, | ||||
|             number=1, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"".decode('utf-8'), | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name='content_type', | ||||
|             full_name='spotify.Header.content_type', | ||||
|             index=1, | ||||
|             number=2, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"".decode('utf-8'), | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name='method', | ||||
|             full_name='spotify.Header.method', | ||||
|             index=2, | ||||
|             number=3, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"".decode('utf-8'), | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name='status_code', | ||||
|             full_name='spotify.Header.status_code', | ||||
|             index=3, | ||||
|             number=4, | ||||
|             type=17, | ||||
|             cpp_type=1, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=0, | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name='user_fields', | ||||
|             full_name='spotify.Header.user_fields', | ||||
|             index=4, | ||||
|             number=6, | ||||
|             type=11, | ||||
|             cpp_type=10, | ||||
|             label=3, | ||||
|             has_default_value=False, | ||||
|             default_value=[], | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key), | ||||
|     ], | ||||
|     extensions=[], | ||||
|     nested_types=[], | ||||
|     enum_types=[], | ||||
|     serialized_options=None, | ||||
|     is_extendable=False, | ||||
|     syntax='proto2', | ||||
|     extension_ranges=[], | ||||
|     oneofs=[], | ||||
|     serialized_start=485, | ||||
|     serialized_end=606, | ||||
| ) | ||||
| 
 | ||||
| _USERFIELD = _descriptor.Descriptor( | ||||
|     name='UserField', | ||||
|     full_name='spotify.UserField', | ||||
|     filename=None, | ||||
|     file=DESCRIPTOR, | ||||
|     containing_type=None, | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     fields=[ | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name='key', | ||||
|             full_name='spotify.UserField.key', | ||||
|             index=0, | ||||
|             number=1, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"".decode('utf-8'), | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name='value', | ||||
|             full_name='spotify.UserField.value', | ||||
|             index=1, | ||||
|             number=2, | ||||
|             type=12, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"", | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key), | ||||
|     ], | ||||
|     extensions=[], | ||||
|     nested_types=[], | ||||
|     enum_types=[], | ||||
|     serialized_options=None, | ||||
|     is_extendable=False, | ||||
|     syntax='proto2', | ||||
|     extension_ranges=[], | ||||
|     oneofs=[], | ||||
|     serialized_start=608, | ||||
|     serialized_end=647, | ||||
| ) | ||||
| 
 | ||||
| _MERCURYMULTIGETREQUEST.fields_by_name[ | ||||
|     'request'].message_type = _MERCURYREQUEST | ||||
| _MERCURYMULTIGETREPLY.fields_by_name['reply'].message_type = _MERCURYREPLY | ||||
| _MERCURYREPLY.fields_by_name[ | ||||
|     'cache_policy'].enum_type = _MERCURYREPLY_CACHEPOLICY | ||||
| _MERCURYREPLY_CACHEPOLICY.containing_type = _MERCURYREPLY | ||||
| _HEADER.fields_by_name['user_fields'].message_type = _USERFIELD | ||||
| DESCRIPTOR.message_types_by_name[ | ||||
|     'MercuryMultiGetRequest'] = _MERCURYMULTIGETREQUEST | ||||
| DESCRIPTOR.message_types_by_name[ | ||||
|     'MercuryMultiGetReply'] = _MERCURYMULTIGETREPLY | ||||
| DESCRIPTOR.message_types_by_name['MercuryRequest'] = _MERCURYREQUEST | ||||
| DESCRIPTOR.message_types_by_name['MercuryReply'] = _MERCURYREPLY | ||||
| DESCRIPTOR.message_types_by_name['Header'] = _HEADER | ||||
| DESCRIPTOR.message_types_by_name['UserField'] = _USERFIELD | ||||
| _sym_db.RegisterFileDescriptor(DESCRIPTOR) | ||||
| 
 | ||||
| MercuryMultiGetRequest = _reflection.GeneratedProtocolMessageType( | ||||
|     'MercuryMultiGetRequest', | ||||
|     (_message.Message, ), | ||||
|     { | ||||
|         'DESCRIPTOR': _MERCURYMULTIGETREQUEST, | ||||
|         '__module__': 'mercury_pb2' | ||||
|         # @@protoc_insertion_point(class_scope:spotify.MercuryMultiGetRequest) | ||||
|     }) | ||||
| _sym_db.RegisterMessage(MercuryMultiGetRequest) | ||||
| 
 | ||||
| MercuryMultiGetReply = _reflection.GeneratedProtocolMessageType( | ||||
|     'MercuryMultiGetReply', | ||||
|     (_message.Message, ), | ||||
|     { | ||||
|         'DESCRIPTOR': _MERCURYMULTIGETREPLY, | ||||
|         '__module__': 'mercury_pb2' | ||||
|         # @@protoc_insertion_point(class_scope:spotify.MercuryMultiGetReply) | ||||
|     }) | ||||
| _sym_db.RegisterMessage(MercuryMultiGetReply) | ||||
| 
 | ||||
| MercuryRequest = _reflection.GeneratedProtocolMessageType( | ||||
|     'MercuryRequest', | ||||
|     (_message.Message, ), | ||||
|     { | ||||
|         'DESCRIPTOR': _MERCURYREQUEST, | ||||
|         '__module__': 'mercury_pb2' | ||||
|         # @@protoc_insertion_point(class_scope:spotify.MercuryRequest) | ||||
|     }) | ||||
| _sym_db.RegisterMessage(MercuryRequest) | ||||
| 
 | ||||
| MercuryReply = _reflection.GeneratedProtocolMessageType( | ||||
|     'MercuryReply', | ||||
|     (_message.Message, ), | ||||
|     { | ||||
|         'DESCRIPTOR': _MERCURYREPLY, | ||||
|         '__module__': 'mercury_pb2' | ||||
|         # @@protoc_insertion_point(class_scope:spotify.MercuryReply) | ||||
|     }) | ||||
| _sym_db.RegisterMessage(MercuryReply) | ||||
| 
 | ||||
| Header = _reflection.GeneratedProtocolMessageType( | ||||
|     'Header', | ||||
|     (_message.Message, ), | ||||
|     { | ||||
|         'DESCRIPTOR': _HEADER, | ||||
|         '__module__': 'mercury_pb2' | ||||
|         # @@protoc_insertion_point(class_scope:spotify.Header) | ||||
|     }) | ||||
| _sym_db.RegisterMessage(Header) | ||||
| 
 | ||||
| UserField = _reflection.GeneratedProtocolMessageType( | ||||
|     'UserField', | ||||
|     (_message.Message, ), | ||||
|     { | ||||
|         'DESCRIPTOR': _USERFIELD, | ||||
|         '__module__': 'mercury_pb2' | ||||
|         # @@protoc_insertion_point(class_scope:spotify.UserField) | ||||
|     }) | ||||
| _sym_db.RegisterMessage(UserField) | ||||
| 
 | ||||
| DESCRIPTOR._options = None | ||||
| # @@protoc_insertion_point(module_scope) | ||||
							
								
								
									
										3698
									
								
								resources/lib/librespot/proto/Metadata_pb2.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										3698
									
								
								resources/lib/librespot/proto/Metadata_pb2.py
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										193
									
								
								resources/lib/librespot/proto/PlayOrigin_pb2.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										193
									
								
								resources/lib/librespot/proto/PlayOrigin_pb2.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,193 @@ | |||
| # -*- coding: utf-8 -*- | ||||
| # Generated by the protocol buffer compiler.  DO NOT EDIT! | ||||
| # source: play_origin.proto | ||||
| """Generated protocol buffer code.""" | ||||
| from google.protobuf import descriptor as _descriptor | ||||
| from google.protobuf import message as _message | ||||
| from google.protobuf import reflection as _reflection | ||||
| from google.protobuf import symbol_database as _symbol_database | ||||
| 
 | ||||
| # @@protoc_insertion_point(imports) | ||||
| 
 | ||||
| _sym_db = _symbol_database.Default() | ||||
| 
 | ||||
| DESCRIPTOR = _descriptor.FileDescriptor( | ||||
|     name="play_origin.proto", | ||||
|     package="spotify.player.proto", | ||||
|     syntax="proto2", | ||||
|     serialized_options=b"\n\023com.spotify.contextH\002", | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     serialized_pb= | ||||
|     b'\n\x11play_origin.proto\x12\x14spotify.player.proto"\xbf\x01\n\nPlayOrigin\x12\x1a\n\x12\x66\x65\x61ture_identifier\x18\x01 \x01(\t\x12\x17\n\x0f\x66\x65\x61ture_version\x18\x02 \x01(\t\x12\x10\n\x08view_uri\x18\x03 \x01(\t\x12\x19\n\x11\x65xternal_referrer\x18\x04 \x01(\t\x12\x1b\n\x13referrer_identifier\x18\x05 \x01(\t\x12\x19\n\x11\x64\x65vice_identifier\x18\x06 \x01(\t\x12\x17\n\x0f\x66\x65\x61ture_classes\x18\x07 \x03(\tB\x17\n\x13\x63om.spotify.contextH\x02', | ||||
| ) | ||||
| 
 | ||||
| _PLAYORIGIN = _descriptor.Descriptor( | ||||
|     name="PlayOrigin", | ||||
|     full_name="spotify.player.proto.PlayOrigin", | ||||
|     filename=None, | ||||
|     file=DESCRIPTOR, | ||||
|     containing_type=None, | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     fields=[ | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="feature_identifier", | ||||
|             full_name="spotify.player.proto.PlayOrigin.feature_identifier", | ||||
|             index=0, | ||||
|             number=1, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"".decode("utf-8"), | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="feature_version", | ||||
|             full_name="spotify.player.proto.PlayOrigin.feature_version", | ||||
|             index=1, | ||||
|             number=2, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"".decode("utf-8"), | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="view_uri", | ||||
|             full_name="spotify.player.proto.PlayOrigin.view_uri", | ||||
|             index=2, | ||||
|             number=3, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"".decode("utf-8"), | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="external_referrer", | ||||
|             full_name="spotify.player.proto.PlayOrigin.external_referrer", | ||||
|             index=3, | ||||
|             number=4, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"".decode("utf-8"), | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="referrer_identifier", | ||||
|             full_name="spotify.player.proto.PlayOrigin.referrer_identifier", | ||||
|             index=4, | ||||
|             number=5, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"".decode("utf-8"), | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="device_identifier", | ||||
|             full_name="spotify.player.proto.PlayOrigin.device_identifier", | ||||
|             index=5, | ||||
|             number=6, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"".decode("utf-8"), | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="feature_classes", | ||||
|             full_name="spotify.player.proto.PlayOrigin.feature_classes", | ||||
|             index=6, | ||||
|             number=7, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=3, | ||||
|             has_default_value=False, | ||||
|             default_value=[], | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|     ], | ||||
|     extensions=[], | ||||
|     nested_types=[], | ||||
|     enum_types=[], | ||||
|     serialized_options=None, | ||||
|     is_extendable=False, | ||||
|     syntax="proto2", | ||||
|     extension_ranges=[], | ||||
|     oneofs=[], | ||||
|     serialized_start=44, | ||||
|     serialized_end=235, | ||||
| ) | ||||
| 
 | ||||
| DESCRIPTOR.message_types_by_name["PlayOrigin"] = _PLAYORIGIN | ||||
| _sym_db.RegisterFileDescriptor(DESCRIPTOR) | ||||
| 
 | ||||
| PlayOrigin = _reflection.GeneratedProtocolMessageType( | ||||
|     "PlayOrigin", | ||||
|     (_message.Message, ), | ||||
|     { | ||||
|         "DESCRIPTOR": _PLAYORIGIN, | ||||
|         "__module__": "play_origin_pb2" | ||||
|         # @@protoc_insertion_point(class_scope:spotify.player.proto.PlayOrigin) | ||||
|     }, | ||||
| ) | ||||
| _sym_db.RegisterMessage(PlayOrigin) | ||||
| 
 | ||||
| DESCRIPTOR._options = None | ||||
| # @@protoc_insertion_point(module_scope) | ||||
							
								
								
									
										162
									
								
								resources/lib/librespot/proto/Playback_pb2.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										162
									
								
								resources/lib/librespot/proto/Playback_pb2.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,162 @@ | |||
| # -*- coding: utf-8 -*- | ||||
| # Generated by the protocol buffer compiler.  DO NOT EDIT! | ||||
| # source: playback.proto | ||||
| """Generated protocol buffer code.""" | ||||
| import ContextTrack_pb2 as context__track__pb2 | ||||
| from google.protobuf import descriptor as _descriptor | ||||
| from google.protobuf import message as _message | ||||
| from google.protobuf import reflection as _reflection | ||||
| from google.protobuf import symbol_database as _symbol_database | ||||
| 
 | ||||
| # @@protoc_insertion_point(imports) | ||||
| 
 | ||||
| _sym_db = _symbol_database.Default() | ||||
| 
 | ||||
| DESCRIPTOR = _descriptor.FileDescriptor( | ||||
|     name="playback.proto", | ||||
|     package="spotify.player.proto.transfer", | ||||
|     syntax="proto2", | ||||
|     serialized_options=b"\n\024com.spotify.transferH\002", | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     serialized_pb= | ||||
|     b'\n\x0eplayback.proto\x12\x1dspotify.player.proto.transfer\x1a\x13\x63ontext_track.proto"\xa5\x01\n\x08Playback\x12\x11\n\ttimestamp\x18\x01 \x01(\x03\x12 \n\x18position_as_of_timestamp\x18\x02 \x01(\x05\x12\x16\n\x0eplayback_speed\x18\x03 \x01(\x01\x12\x11\n\tis_paused\x18\x04 \x01(\x08\x12\x39\n\rcurrent_track\x18\x05 \x01(\x0b\x32".spotify.player.proto.ContextTrackB\x18\n\x14\x63om.spotify.transferH\x02', | ||||
|     dependencies=[ | ||||
|         context__track__pb2.DESCRIPTOR, | ||||
|     ], | ||||
| ) | ||||
| 
 | ||||
| _PLAYBACK = _descriptor.Descriptor( | ||||
|     name="Playback", | ||||
|     full_name="spotify.player.proto.transfer.Playback", | ||||
|     filename=None, | ||||
|     file=DESCRIPTOR, | ||||
|     containing_type=None, | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     fields=[ | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="timestamp", | ||||
|             full_name="spotify.player.proto.transfer.Playback.timestamp", | ||||
|             index=0, | ||||
|             number=1, | ||||
|             type=3, | ||||
|             cpp_type=2, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=0, | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="position_as_of_timestamp", | ||||
|             full_name= | ||||
|             "spotify.player.proto.transfer.Playback.position_as_of_timestamp", | ||||
|             index=1, | ||||
|             number=2, | ||||
|             type=5, | ||||
|             cpp_type=1, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=0, | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="playback_speed", | ||||
|             full_name="spotify.player.proto.transfer.Playback.playback_speed", | ||||
|             index=2, | ||||
|             number=3, | ||||
|             type=1, | ||||
|             cpp_type=5, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=float(0), | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="is_paused", | ||||
|             full_name="spotify.player.proto.transfer.Playback.is_paused", | ||||
|             index=3, | ||||
|             number=4, | ||||
|             type=8, | ||||
|             cpp_type=7, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=False, | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="current_track", | ||||
|             full_name="spotify.player.proto.transfer.Playback.current_track", | ||||
|             index=4, | ||||
|             number=5, | ||||
|             type=11, | ||||
|             cpp_type=10, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=None, | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|     ], | ||||
|     extensions=[], | ||||
|     nested_types=[], | ||||
|     enum_types=[], | ||||
|     serialized_options=None, | ||||
|     is_extendable=False, | ||||
|     syntax="proto2", | ||||
|     extension_ranges=[], | ||||
|     oneofs=[], | ||||
|     serialized_start=71, | ||||
|     serialized_end=236, | ||||
| ) | ||||
| 
 | ||||
| _PLAYBACK.fields_by_name[ | ||||
|     "current_track"].message_type = context__track__pb2._CONTEXTTRACK | ||||
| DESCRIPTOR.message_types_by_name["Playback"] = _PLAYBACK | ||||
| _sym_db.RegisterFileDescriptor(DESCRIPTOR) | ||||
| 
 | ||||
| Playback = _reflection.GeneratedProtocolMessageType( | ||||
|     "Playback", | ||||
|     (_message.Message, ), | ||||
|     { | ||||
|         "DESCRIPTOR": _PLAYBACK, | ||||
|         "__module__": "playback_pb2" | ||||
|         # @@protoc_insertion_point(class_scope:spotify.player.proto.transfer.Playback) | ||||
|     }, | ||||
| ) | ||||
| _sym_db.RegisterMessage(Playback) | ||||
| 
 | ||||
| DESCRIPTOR._options = None | ||||
| # @@protoc_insertion_point(module_scope) | ||||
							
								
								
									
										1851
									
								
								resources/lib/librespot/proto/Player_pb2.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1851
									
								
								resources/lib/librespot/proto/Player_pb2.py
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										3221
									
								
								resources/lib/librespot/proto/Playlist4External_pb2.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										3221
									
								
								resources/lib/librespot/proto/Playlist4External_pb2.py
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										460
									
								
								resources/lib/librespot/proto/PlaylistAnnotate3_pb2.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										460
									
								
								resources/lib/librespot/proto/PlaylistAnnotate3_pb2.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,460 @@ | |||
| # -*- coding: utf-8 -*- | ||||
| # Generated by the protocol buffer compiler.  DO NOT EDIT! | ||||
| # source: playlist_annotate3.proto | ||||
| """Generated protocol buffer code.""" | ||||
| from google.protobuf import descriptor as _descriptor | ||||
| from google.protobuf import message as _message | ||||
| from google.protobuf import reflection as _reflection | ||||
| from google.protobuf import symbol_database as _symbol_database | ||||
| from google.protobuf.internal import enum_type_wrapper | ||||
| 
 | ||||
| # @@protoc_insertion_point(imports) | ||||
| 
 | ||||
| _sym_db = _symbol_database.Default() | ||||
| 
 | ||||
| DESCRIPTOR = _descriptor.FileDescriptor( | ||||
|     name="playlist_annotate3.proto", | ||||
|     package="spotify_playlist_annotate3.proto", | ||||
|     syntax="proto2", | ||||
|     serialized_options=b"\n\036com.spotify.playlist_annotate3H\002", | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     serialized_pb= | ||||
|     b'\n\x18playlist_annotate3.proto\x12 spotify_playlist_annotate3.proto"a\n\x0fTakedownRequest\x12N\n\x12\x61\x62use_report_state\x18\x01 \x01(\x0e\x32\x32.spotify_playlist_annotate3.proto.AbuseReportState"9\n\x0f\x41nnotateRequest\x12\x13\n\x0b\x64\x65scription\x18\x01 \x01(\t\x12\x11\n\timage_uri\x18\x02 \x01(\t"5\n\x11TranscodedPicture\x12\x13\n\x0btarget_name\x18\x01 \x01(\t\x12\x0b\n\x03uri\x18\x02 \x01(\t"\xf4\x02\n\x12PlaylistAnnotation\x12\x13\n\x0b\x64\x65scription\x18\x01 \x01(\t\x12\x0f\n\x07picture\x18\x02 \x01(\t\x12i\n\x1a\x64\x65precated_render_features\x18\x03 \x01(\x0e\x32\x30.spotify_playlist_annotate3.proto.RenderFeatures:\x0fNORMAL_FEATURESB\x02\x18\x01\x12O\n\x12transcoded_picture\x18\x04 \x03(\x0b\x32\x33.spotify_playlist_annotate3.proto.TranscodedPicture\x12(\n\x1ais_abuse_reporting_enabled\x18\x06 \x01(\x08:\x04true\x12R\n\x12\x61\x62use_report_state\x18\x07 \x01(\x0e\x32\x32.spotify_playlist_annotate3.proto.AbuseReportState:\x02OK*<\n\x0eRenderFeatures\x12\x13\n\x0fNORMAL_FEATURES\x10\x01\x12\x15\n\x11\x45XTENDED_FEATURES\x10\x02**\n\x10\x41\x62useReportState\x12\x06\n\x02OK\x10\x00\x12\x0e\n\nTAKEN_DOWN\x10\x01\x42"\n\x1e\x63om.spotify.playlist_annotate3H\x02', | ||||
| ) | ||||
| 
 | ||||
| _RENDERFEATURES = _descriptor.EnumDescriptor( | ||||
|     name="RenderFeatures", | ||||
|     full_name="spotify_playlist_annotate3.proto.RenderFeatures", | ||||
|     filename=None, | ||||
|     file=DESCRIPTOR, | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     values=[ | ||||
|         _descriptor.EnumValueDescriptor( | ||||
|             name="NORMAL_FEATURES", | ||||
|             index=0, | ||||
|             number=1, | ||||
|             serialized_options=None, | ||||
|             type=None, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.EnumValueDescriptor( | ||||
|             name="EXTENDED_FEATURES", | ||||
|             index=1, | ||||
|             number=2, | ||||
|             serialized_options=None, | ||||
|             type=None, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|     ], | ||||
|     containing_type=None, | ||||
|     serialized_options=None, | ||||
|     serialized_start=650, | ||||
|     serialized_end=710, | ||||
| ) | ||||
| _sym_db.RegisterEnumDescriptor(_RENDERFEATURES) | ||||
| 
 | ||||
| RenderFeatures = enum_type_wrapper.EnumTypeWrapper(_RENDERFEATURES) | ||||
| _ABUSEREPORTSTATE = _descriptor.EnumDescriptor( | ||||
|     name="AbuseReportState", | ||||
|     full_name="spotify_playlist_annotate3.proto.AbuseReportState", | ||||
|     filename=None, | ||||
|     file=DESCRIPTOR, | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     values=[ | ||||
|         _descriptor.EnumValueDescriptor( | ||||
|             name="OK", | ||||
|             index=0, | ||||
|             number=0, | ||||
|             serialized_options=None, | ||||
|             type=None, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.EnumValueDescriptor( | ||||
|             name="TAKEN_DOWN", | ||||
|             index=1, | ||||
|             number=1, | ||||
|             serialized_options=None, | ||||
|             type=None, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|     ], | ||||
|     containing_type=None, | ||||
|     serialized_options=None, | ||||
|     serialized_start=712, | ||||
|     serialized_end=754, | ||||
| ) | ||||
| _sym_db.RegisterEnumDescriptor(_ABUSEREPORTSTATE) | ||||
| 
 | ||||
| AbuseReportState = enum_type_wrapper.EnumTypeWrapper(_ABUSEREPORTSTATE) | ||||
| NORMAL_FEATURES = 1 | ||||
| EXTENDED_FEATURES = 2 | ||||
| OK = 0 | ||||
| TAKEN_DOWN = 1 | ||||
| 
 | ||||
| _TAKEDOWNREQUEST = _descriptor.Descriptor( | ||||
|     name="TakedownRequest", | ||||
|     full_name="spotify_playlist_annotate3.proto.TakedownRequest", | ||||
|     filename=None, | ||||
|     file=DESCRIPTOR, | ||||
|     containing_type=None, | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     fields=[ | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="abuse_report_state", | ||||
|             full_name= | ||||
|             "spotify_playlist_annotate3.proto.TakedownRequest.abuse_report_state", | ||||
|             index=0, | ||||
|             number=1, | ||||
|             type=14, | ||||
|             cpp_type=8, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=0, | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|     ], | ||||
|     extensions=[], | ||||
|     nested_types=[], | ||||
|     enum_types=[], | ||||
|     serialized_options=None, | ||||
|     is_extendable=False, | ||||
|     syntax="proto2", | ||||
|     extension_ranges=[], | ||||
|     oneofs=[], | ||||
|     serialized_start=62, | ||||
|     serialized_end=159, | ||||
| ) | ||||
| 
 | ||||
| _ANNOTATEREQUEST = _descriptor.Descriptor( | ||||
|     name="AnnotateRequest", | ||||
|     full_name="spotify_playlist_annotate3.proto.AnnotateRequest", | ||||
|     filename=None, | ||||
|     file=DESCRIPTOR, | ||||
|     containing_type=None, | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     fields=[ | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="description", | ||||
|             full_name= | ||||
|             "spotify_playlist_annotate3.proto.AnnotateRequest.description", | ||||
|             index=0, | ||||
|             number=1, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"".decode("utf-8"), | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="image_uri", | ||||
|             full_name= | ||||
|             "spotify_playlist_annotate3.proto.AnnotateRequest.image_uri", | ||||
|             index=1, | ||||
|             number=2, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"".decode("utf-8"), | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|     ], | ||||
|     extensions=[], | ||||
|     nested_types=[], | ||||
|     enum_types=[], | ||||
|     serialized_options=None, | ||||
|     is_extendable=False, | ||||
|     syntax="proto2", | ||||
|     extension_ranges=[], | ||||
|     oneofs=[], | ||||
|     serialized_start=161, | ||||
|     serialized_end=218, | ||||
| ) | ||||
| 
 | ||||
| _TRANSCODEDPICTURE = _descriptor.Descriptor( | ||||
|     name="TranscodedPicture", | ||||
|     full_name="spotify_playlist_annotate3.proto.TranscodedPicture", | ||||
|     filename=None, | ||||
|     file=DESCRIPTOR, | ||||
|     containing_type=None, | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     fields=[ | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="target_name", | ||||
|             full_name= | ||||
|             "spotify_playlist_annotate3.proto.TranscodedPicture.target_name", | ||||
|             index=0, | ||||
|             number=1, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"".decode("utf-8"), | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="uri", | ||||
|             full_name="spotify_playlist_annotate3.proto.TranscodedPicture.uri", | ||||
|             index=1, | ||||
|             number=2, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"".decode("utf-8"), | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|     ], | ||||
|     extensions=[], | ||||
|     nested_types=[], | ||||
|     enum_types=[], | ||||
|     serialized_options=None, | ||||
|     is_extendable=False, | ||||
|     syntax="proto2", | ||||
|     extension_ranges=[], | ||||
|     oneofs=[], | ||||
|     serialized_start=220, | ||||
|     serialized_end=273, | ||||
| ) | ||||
| 
 | ||||
| _PLAYLISTANNOTATION = _descriptor.Descriptor( | ||||
|     name="PlaylistAnnotation", | ||||
|     full_name="spotify_playlist_annotate3.proto.PlaylistAnnotation", | ||||
|     filename=None, | ||||
|     file=DESCRIPTOR, | ||||
|     containing_type=None, | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     fields=[ | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="description", | ||||
|             full_name= | ||||
|             "spotify_playlist_annotate3.proto.PlaylistAnnotation.description", | ||||
|             index=0, | ||||
|             number=1, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"".decode("utf-8"), | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="picture", | ||||
|             full_name= | ||||
|             "spotify_playlist_annotate3.proto.PlaylistAnnotation.picture", | ||||
|             index=1, | ||||
|             number=2, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"".decode("utf-8"), | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="deprecated_render_features", | ||||
|             full_name= | ||||
|             "spotify_playlist_annotate3.proto.PlaylistAnnotation.deprecated_render_features", | ||||
|             index=2, | ||||
|             number=3, | ||||
|             type=14, | ||||
|             cpp_type=8, | ||||
|             label=1, | ||||
|             has_default_value=True, | ||||
|             default_value=1, | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=b"\030\001", | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="transcoded_picture", | ||||
|             full_name= | ||||
|             "spotify_playlist_annotate3.proto.PlaylistAnnotation.transcoded_picture", | ||||
|             index=3, | ||||
|             number=4, | ||||
|             type=11, | ||||
|             cpp_type=10, | ||||
|             label=3, | ||||
|             has_default_value=False, | ||||
|             default_value=[], | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="is_abuse_reporting_enabled", | ||||
|             full_name= | ||||
|             "spotify_playlist_annotate3.proto.PlaylistAnnotation.is_abuse_reporting_enabled", | ||||
|             index=4, | ||||
|             number=6, | ||||
|             type=8, | ||||
|             cpp_type=7, | ||||
|             label=1, | ||||
|             has_default_value=True, | ||||
|             default_value=True, | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="abuse_report_state", | ||||
|             full_name= | ||||
|             "spotify_playlist_annotate3.proto.PlaylistAnnotation.abuse_report_state", | ||||
|             index=5, | ||||
|             number=7, | ||||
|             type=14, | ||||
|             cpp_type=8, | ||||
|             label=1, | ||||
|             has_default_value=True, | ||||
|             default_value=0, | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|     ], | ||||
|     extensions=[], | ||||
|     nested_types=[], | ||||
|     enum_types=[], | ||||
|     serialized_options=None, | ||||
|     is_extendable=False, | ||||
|     syntax="proto2", | ||||
|     extension_ranges=[], | ||||
|     oneofs=[], | ||||
|     serialized_start=276, | ||||
|     serialized_end=648, | ||||
| ) | ||||
| 
 | ||||
| _TAKEDOWNREQUEST.fields_by_name[ | ||||
|     "abuse_report_state"].enum_type = _ABUSEREPORTSTATE | ||||
| _PLAYLISTANNOTATION.fields_by_name[ | ||||
|     "deprecated_render_features"].enum_type = _RENDERFEATURES | ||||
| _PLAYLISTANNOTATION.fields_by_name[ | ||||
|     "transcoded_picture"].message_type = _TRANSCODEDPICTURE | ||||
| _PLAYLISTANNOTATION.fields_by_name[ | ||||
|     "abuse_report_state"].enum_type = _ABUSEREPORTSTATE | ||||
| DESCRIPTOR.message_types_by_name["TakedownRequest"] = _TAKEDOWNREQUEST | ||||
| DESCRIPTOR.message_types_by_name["AnnotateRequest"] = _ANNOTATEREQUEST | ||||
| DESCRIPTOR.message_types_by_name["TranscodedPicture"] = _TRANSCODEDPICTURE | ||||
| DESCRIPTOR.message_types_by_name["PlaylistAnnotation"] = _PLAYLISTANNOTATION | ||||
| DESCRIPTOR.enum_types_by_name["RenderFeatures"] = _RENDERFEATURES | ||||
| DESCRIPTOR.enum_types_by_name["AbuseReportState"] = _ABUSEREPORTSTATE | ||||
| _sym_db.RegisterFileDescriptor(DESCRIPTOR) | ||||
| 
 | ||||
| TakedownRequest = _reflection.GeneratedProtocolMessageType( | ||||
|     "TakedownRequest", | ||||
|     (_message.Message, ), | ||||
|     { | ||||
|         "DESCRIPTOR": _TAKEDOWNREQUEST, | ||||
|         "__module__": "playlist_annotate3_pb2" | ||||
|         # @@protoc_insertion_point(class_scope:spotify_playlist_annotate3.proto.TakedownRequest) | ||||
|     }, | ||||
| ) | ||||
| _sym_db.RegisterMessage(TakedownRequest) | ||||
| 
 | ||||
| AnnotateRequest = _reflection.GeneratedProtocolMessageType( | ||||
|     "AnnotateRequest", | ||||
|     (_message.Message, ), | ||||
|     { | ||||
|         "DESCRIPTOR": _ANNOTATEREQUEST, | ||||
|         "__module__": "playlist_annotate3_pb2" | ||||
|         # @@protoc_insertion_point(class_scope:spotify_playlist_annotate3.proto.AnnotateRequest) | ||||
|     }, | ||||
| ) | ||||
| _sym_db.RegisterMessage(AnnotateRequest) | ||||
| 
 | ||||
| TranscodedPicture = _reflection.GeneratedProtocolMessageType( | ||||
|     "TranscodedPicture", | ||||
|     (_message.Message, ), | ||||
|     { | ||||
|         "DESCRIPTOR": _TRANSCODEDPICTURE, | ||||
|         "__module__": "playlist_annotate3_pb2" | ||||
|         # @@protoc_insertion_point(class_scope:spotify_playlist_annotate3.proto.TranscodedPicture) | ||||
|     }, | ||||
| ) | ||||
| _sym_db.RegisterMessage(TranscodedPicture) | ||||
| 
 | ||||
| PlaylistAnnotation = _reflection.GeneratedProtocolMessageType( | ||||
|     "PlaylistAnnotation", | ||||
|     (_message.Message, ), | ||||
|     { | ||||
|         "DESCRIPTOR": _PLAYLISTANNOTATION, | ||||
|         "__module__": "playlist_annotate3_pb2" | ||||
|         # @@protoc_insertion_point(class_scope:spotify_playlist_annotate3.proto.PlaylistAnnotation) | ||||
|     }, | ||||
| ) | ||||
| _sym_db.RegisterMessage(PlaylistAnnotation) | ||||
| 
 | ||||
| DESCRIPTOR._options = None | ||||
| _PLAYLISTANNOTATION.fields_by_name[ | ||||
|     "deprecated_render_features"]._options = None | ||||
| # @@protoc_insertion_point(module_scope) | ||||
							
								
								
									
										112
									
								
								resources/lib/librespot/proto/Pubsub_pb2.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										112
									
								
								resources/lib/librespot/proto/Pubsub_pb2.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,112 @@ | |||
| # -*- coding: utf-8 -*- | ||||
| # Generated by the protocol buffer compiler.  DO NOT EDIT! | ||||
| # source: pubsub.proto | ||||
| """Generated protocol buffer code.""" | ||||
| from google.protobuf import descriptor as _descriptor | ||||
| from google.protobuf import message as _message | ||||
| from google.protobuf import reflection as _reflection | ||||
| from google.protobuf import symbol_database as _symbol_database | ||||
| # @@protoc_insertion_point(imports) | ||||
| 
 | ||||
| _sym_db = _symbol_database.Default() | ||||
| 
 | ||||
| DESCRIPTOR = _descriptor.FileDescriptor( | ||||
|     name='pubsub.proto', | ||||
|     package='spotify', | ||||
|     syntax='proto2', | ||||
|     serialized_options=b'\n\013com.spotify', | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     serialized_pb= | ||||
|     b'\n\x0cpubsub.proto\x12\x07spotify\"@\n\x0cSubscription\x12\x0b\n\x03uri\x18\x01 \x01(\t\x12\x0e\n\x06\x65xpiry\x18\x02 \x01(\x05\x12\x13\n\x0bstatus_code\x18\x03 \x01(\x05\x42\r\n\x0b\x63om.spotify' | ||||
| ) | ||||
| 
 | ||||
| _SUBSCRIPTION = _descriptor.Descriptor( | ||||
|     name='Subscription', | ||||
|     full_name='spotify.Subscription', | ||||
|     filename=None, | ||||
|     file=DESCRIPTOR, | ||||
|     containing_type=None, | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     fields=[ | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name='uri', | ||||
|             full_name='spotify.Subscription.uri', | ||||
|             index=0, | ||||
|             number=1, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"".decode('utf-8'), | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name='expiry', | ||||
|             full_name='spotify.Subscription.expiry', | ||||
|             index=1, | ||||
|             number=2, | ||||
|             type=5, | ||||
|             cpp_type=1, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=0, | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name='status_code', | ||||
|             full_name='spotify.Subscription.status_code', | ||||
|             index=2, | ||||
|             number=3, | ||||
|             type=5, | ||||
|             cpp_type=1, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=0, | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key), | ||||
|     ], | ||||
|     extensions=[], | ||||
|     nested_types=[], | ||||
|     enum_types=[], | ||||
|     serialized_options=None, | ||||
|     is_extendable=False, | ||||
|     syntax='proto2', | ||||
|     extension_ranges=[], | ||||
|     oneofs=[], | ||||
|     serialized_start=25, | ||||
|     serialized_end=89, | ||||
| ) | ||||
| 
 | ||||
| DESCRIPTOR.message_types_by_name['Subscription'] = _SUBSCRIPTION | ||||
| _sym_db.RegisterFileDescriptor(DESCRIPTOR) | ||||
| 
 | ||||
| Subscription = _reflection.GeneratedProtocolMessageType( | ||||
|     'Subscription', | ||||
|     (_message.Message, ), | ||||
|     { | ||||
|         'DESCRIPTOR': _SUBSCRIPTION, | ||||
|         '__module__': 'pubsub_pb2' | ||||
|         # @@protoc_insertion_point(class_scope:spotify.Subscription) | ||||
|     }) | ||||
| _sym_db.RegisterMessage(Subscription) | ||||
| 
 | ||||
| DESCRIPTOR._options = None | ||||
| # @@protoc_insertion_point(module_scope) | ||||
							
								
								
									
										104
									
								
								resources/lib/librespot/proto/Queue_pb2.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										104
									
								
								resources/lib/librespot/proto/Queue_pb2.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,104 @@ | |||
| # -*- coding: utf-8 -*- | ||||
| # Generated by the protocol buffer compiler.  DO NOT EDIT! | ||||
| # source: queue.proto | ||||
| """Generated protocol buffer code.""" | ||||
| import ContextTrack_pb2 as context__track__pb2 | ||||
| from google.protobuf import descriptor as _descriptor | ||||
| from google.protobuf import message as _message | ||||
| from google.protobuf import reflection as _reflection | ||||
| from google.protobuf import symbol_database as _symbol_database | ||||
| 
 | ||||
| # @@protoc_insertion_point(imports) | ||||
| 
 | ||||
| _sym_db = _symbol_database.Default() | ||||
| 
 | ||||
| DESCRIPTOR = _descriptor.FileDescriptor( | ||||
|     name="queue.proto", | ||||
|     package="spotify.player.proto.transfer", | ||||
|     syntax="proto2", | ||||
|     serialized_options=b"\n\024com.spotify.transferH\002", | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     serialized_pb= | ||||
|     b'\n\x0bqueue.proto\x12\x1dspotify.player.proto.transfer\x1a\x13\x63ontext_track.proto"U\n\x05Queue\x12\x32\n\x06tracks\x18\x01 \x03(\x0b\x32".spotify.player.proto.ContextTrack\x12\x18\n\x10is_playing_queue\x18\x02 \x01(\x08\x42\x18\n\x14\x63om.spotify.transferH\x02', | ||||
|     dependencies=[ | ||||
|         context__track__pb2.DESCRIPTOR, | ||||
|     ], | ||||
| ) | ||||
| 
 | ||||
| _QUEUE = _descriptor.Descriptor( | ||||
|     name="Queue", | ||||
|     full_name="spotify.player.proto.transfer.Queue", | ||||
|     filename=None, | ||||
|     file=DESCRIPTOR, | ||||
|     containing_type=None, | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     fields=[ | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="tracks", | ||||
|             full_name="spotify.player.proto.transfer.Queue.tracks", | ||||
|             index=0, | ||||
|             number=1, | ||||
|             type=11, | ||||
|             cpp_type=10, | ||||
|             label=3, | ||||
|             has_default_value=False, | ||||
|             default_value=[], | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="is_playing_queue", | ||||
|             full_name="spotify.player.proto.transfer.Queue.is_playing_queue", | ||||
|             index=1, | ||||
|             number=2, | ||||
|             type=8, | ||||
|             cpp_type=7, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=False, | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|     ], | ||||
|     extensions=[], | ||||
|     nested_types=[], | ||||
|     enum_types=[], | ||||
|     serialized_options=None, | ||||
|     is_extendable=False, | ||||
|     syntax="proto2", | ||||
|     extension_ranges=[], | ||||
|     oneofs=[], | ||||
|     serialized_start=67, | ||||
|     serialized_end=152, | ||||
| ) | ||||
| 
 | ||||
| _QUEUE.fields_by_name[ | ||||
|     "tracks"].message_type = context__track__pb2._CONTEXTTRACK | ||||
| DESCRIPTOR.message_types_by_name["Queue"] = _QUEUE | ||||
| _sym_db.RegisterFileDescriptor(DESCRIPTOR) | ||||
| 
 | ||||
| Queue = _reflection.GeneratedProtocolMessageType( | ||||
|     "Queue", | ||||
|     (_message.Message, ), | ||||
|     { | ||||
|         "DESCRIPTOR": _QUEUE, | ||||
|         "__module__": "queue_pb2" | ||||
|         # @@protoc_insertion_point(class_scope:spotify.player.proto.transfer.Queue) | ||||
|     }, | ||||
| ) | ||||
| _sym_db.RegisterMessage(Queue) | ||||
| 
 | ||||
| DESCRIPTOR._options = None | ||||
| # @@protoc_insertion_point(module_scope) | ||||
							
								
								
									
										480
									
								
								resources/lib/librespot/proto/Restrictions_pb2.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										480
									
								
								resources/lib/librespot/proto/Restrictions_pb2.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,480 @@ | |||
| # -*- coding: utf-8 -*- | ||||
| # Generated by the protocol buffer compiler.  DO NOT EDIT! | ||||
| # source: restrictions.proto | ||||
| """Generated protocol buffer code.""" | ||||
| from google.protobuf import descriptor as _descriptor | ||||
| from google.protobuf import message as _message | ||||
| from google.protobuf import reflection as _reflection | ||||
| from google.protobuf import symbol_database as _symbol_database | ||||
| 
 | ||||
| # @@protoc_insertion_point(imports) | ||||
| 
 | ||||
| _sym_db = _symbol_database.Default() | ||||
| 
 | ||||
| DESCRIPTOR = _descriptor.FileDescriptor( | ||||
|     name="restrictions.proto", | ||||
|     package="spotify.player.proto", | ||||
|     syntax="proto2", | ||||
|     serialized_options=b"\n\023com.spotify.contextH\002", | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     serialized_pb= | ||||
|     b'\n\x12restrictions.proto\x12\x14spotify.player.proto"\xbb\x07\n\x0cRestrictions\x12 \n\x18\x64isallow_pausing_reasons\x18\x01 \x03(\t\x12!\n\x19\x64isallow_resuming_reasons\x18\x02 \x03(\t\x12 \n\x18\x64isallow_seeking_reasons\x18\x03 \x03(\t\x12%\n\x1d\x64isallow_peeking_prev_reasons\x18\x04 \x03(\t\x12%\n\x1d\x64isallow_peeking_next_reasons\x18\x05 \x03(\t\x12&\n\x1e\x64isallow_skipping_prev_reasons\x18\x06 \x03(\t\x12&\n\x1e\x64isallow_skipping_next_reasons\x18\x07 \x03(\t\x12\x30\n(disallow_toggling_repeat_context_reasons\x18\x08 \x03(\t\x12.\n&disallow_toggling_repeat_track_reasons\x18\t \x03(\t\x12)\n!disallow_toggling_shuffle_reasons\x18\n \x03(\t\x12"\n\x1a\x64isallow_set_queue_reasons\x18\x0b \x03(\t\x12.\n&disallow_interrupting_playback_reasons\x18\x0c \x03(\t\x12.\n&disallow_transferring_playback_reasons\x18\r \x03(\t\x12\'\n\x1f\x64isallow_remote_control_reasons\x18\x0e \x03(\t\x12\x33\n+disallow_inserting_into_next_tracks_reasons\x18\x0f \x03(\t\x12\x36\n.disallow_inserting_into_context_tracks_reasons\x18\x10 \x03(\t\x12\x32\n*disallow_reordering_in_next_tracks_reasons\x18\x11 \x03(\t\x12\x35\n-disallow_reordering_in_context_tracks_reasons\x18\x12 \x03(\t\x12\x32\n*disallow_removing_from_next_tracks_reasons\x18\x13 \x03(\t\x12\x35\n-disallow_removing_from_context_tracks_reasons\x18\x14 \x03(\t\x12)\n!disallow_updating_context_reasons\x18\x15 \x03(\tB\x17\n\x13\x63om.spotify.contextH\x02', | ||||
| ) | ||||
| 
 | ||||
| _RESTRICTIONS = _descriptor.Descriptor( | ||||
|     name="Restrictions", | ||||
|     full_name="spotify.player.proto.Restrictions", | ||||
|     filename=None, | ||||
|     file=DESCRIPTOR, | ||||
|     containing_type=None, | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     fields=[ | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="disallow_pausing_reasons", | ||||
|             full_name= | ||||
|             "spotify.player.proto.Restrictions.disallow_pausing_reasons", | ||||
|             index=0, | ||||
|             number=1, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=3, | ||||
|             has_default_value=False, | ||||
|             default_value=[], | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="disallow_resuming_reasons", | ||||
|             full_name= | ||||
|             "spotify.player.proto.Restrictions.disallow_resuming_reasons", | ||||
|             index=1, | ||||
|             number=2, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=3, | ||||
|             has_default_value=False, | ||||
|             default_value=[], | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="disallow_seeking_reasons", | ||||
|             full_name= | ||||
|             "spotify.player.proto.Restrictions.disallow_seeking_reasons", | ||||
|             index=2, | ||||
|             number=3, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=3, | ||||
|             has_default_value=False, | ||||
|             default_value=[], | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="disallow_peeking_prev_reasons", | ||||
|             full_name= | ||||
|             "spotify.player.proto.Restrictions.disallow_peeking_prev_reasons", | ||||
|             index=3, | ||||
|             number=4, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=3, | ||||
|             has_default_value=False, | ||||
|             default_value=[], | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="disallow_peeking_next_reasons", | ||||
|             full_name= | ||||
|             "spotify.player.proto.Restrictions.disallow_peeking_next_reasons", | ||||
|             index=4, | ||||
|             number=5, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=3, | ||||
|             has_default_value=False, | ||||
|             default_value=[], | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="disallow_skipping_prev_reasons", | ||||
|             full_name= | ||||
|             "spotify.player.proto.Restrictions.disallow_skipping_prev_reasons", | ||||
|             index=5, | ||||
|             number=6, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=3, | ||||
|             has_default_value=False, | ||||
|             default_value=[], | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="disallow_skipping_next_reasons", | ||||
|             full_name= | ||||
|             "spotify.player.proto.Restrictions.disallow_skipping_next_reasons", | ||||
|             index=6, | ||||
|             number=7, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=3, | ||||
|             has_default_value=False, | ||||
|             default_value=[], | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="disallow_toggling_repeat_context_reasons", | ||||
|             full_name= | ||||
|             "spotify.player.proto.Restrictions.disallow_toggling_repeat_context_reasons", | ||||
|             index=7, | ||||
|             number=8, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=3, | ||||
|             has_default_value=False, | ||||
|             default_value=[], | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="disallow_toggling_repeat_track_reasons", | ||||
|             full_name= | ||||
|             "spotify.player.proto.Restrictions.disallow_toggling_repeat_track_reasons", | ||||
|             index=8, | ||||
|             number=9, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=3, | ||||
|             has_default_value=False, | ||||
|             default_value=[], | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="disallow_toggling_shuffle_reasons", | ||||
|             full_name= | ||||
|             "spotify.player.proto.Restrictions.disallow_toggling_shuffle_reasons", | ||||
|             index=9, | ||||
|             number=10, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=3, | ||||
|             has_default_value=False, | ||||
|             default_value=[], | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="disallow_set_queue_reasons", | ||||
|             full_name= | ||||
|             "spotify.player.proto.Restrictions.disallow_set_queue_reasons", | ||||
|             index=10, | ||||
|             number=11, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=3, | ||||
|             has_default_value=False, | ||||
|             default_value=[], | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="disallow_interrupting_playback_reasons", | ||||
|             full_name= | ||||
|             "spotify.player.proto.Restrictions.disallow_interrupting_playback_reasons", | ||||
|             index=11, | ||||
|             number=12, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=3, | ||||
|             has_default_value=False, | ||||
|             default_value=[], | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="disallow_transferring_playback_reasons", | ||||
|             full_name= | ||||
|             "spotify.player.proto.Restrictions.disallow_transferring_playback_reasons", | ||||
|             index=12, | ||||
|             number=13, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=3, | ||||
|             has_default_value=False, | ||||
|             default_value=[], | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="disallow_remote_control_reasons", | ||||
|             full_name= | ||||
|             "spotify.player.proto.Restrictions.disallow_remote_control_reasons", | ||||
|             index=13, | ||||
|             number=14, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=3, | ||||
|             has_default_value=False, | ||||
|             default_value=[], | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="disallow_inserting_into_next_tracks_reasons", | ||||
|             full_name= | ||||
|             "spotify.player.proto.Restrictions.disallow_inserting_into_next_tracks_reasons", | ||||
|             index=14, | ||||
|             number=15, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=3, | ||||
|             has_default_value=False, | ||||
|             default_value=[], | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="disallow_inserting_into_context_tracks_reasons", | ||||
|             full_name= | ||||
|             "spotify.player.proto.Restrictions.disallow_inserting_into_context_tracks_reasons", | ||||
|             index=15, | ||||
|             number=16, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=3, | ||||
|             has_default_value=False, | ||||
|             default_value=[], | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="disallow_reordering_in_next_tracks_reasons", | ||||
|             full_name= | ||||
|             "spotify.player.proto.Restrictions.disallow_reordering_in_next_tracks_reasons", | ||||
|             index=16, | ||||
|             number=17, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=3, | ||||
|             has_default_value=False, | ||||
|             default_value=[], | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="disallow_reordering_in_context_tracks_reasons", | ||||
|             full_name= | ||||
|             "spotify.player.proto.Restrictions.disallow_reordering_in_context_tracks_reasons", | ||||
|             index=17, | ||||
|             number=18, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=3, | ||||
|             has_default_value=False, | ||||
|             default_value=[], | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="disallow_removing_from_next_tracks_reasons", | ||||
|             full_name= | ||||
|             "spotify.player.proto.Restrictions.disallow_removing_from_next_tracks_reasons", | ||||
|             index=18, | ||||
|             number=19, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=3, | ||||
|             has_default_value=False, | ||||
|             default_value=[], | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="disallow_removing_from_context_tracks_reasons", | ||||
|             full_name= | ||||
|             "spotify.player.proto.Restrictions.disallow_removing_from_context_tracks_reasons", | ||||
|             index=19, | ||||
|             number=20, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=3, | ||||
|             has_default_value=False, | ||||
|             default_value=[], | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="disallow_updating_context_reasons", | ||||
|             full_name= | ||||
|             "spotify.player.proto.Restrictions.disallow_updating_context_reasons", | ||||
|             index=20, | ||||
|             number=21, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=3, | ||||
|             has_default_value=False, | ||||
|             default_value=[], | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|     ], | ||||
|     extensions=[], | ||||
|     nested_types=[], | ||||
|     enum_types=[], | ||||
|     serialized_options=None, | ||||
|     is_extendable=False, | ||||
|     syntax="proto2", | ||||
|     extension_ranges=[], | ||||
|     oneofs=[], | ||||
|     serialized_start=45, | ||||
|     serialized_end=1000, | ||||
| ) | ||||
| 
 | ||||
| DESCRIPTOR.message_types_by_name["Restrictions"] = _RESTRICTIONS | ||||
| _sym_db.RegisterFileDescriptor(DESCRIPTOR) | ||||
| 
 | ||||
| Restrictions = _reflection.GeneratedProtocolMessageType( | ||||
|     "Restrictions", | ||||
|     (_message.Message, ), | ||||
|     { | ||||
|         "DESCRIPTOR": _RESTRICTIONS, | ||||
|         "__module__": "restrictions_pb2" | ||||
|         # @@protoc_insertion_point(class_scope:spotify.player.proto.Restrictions) | ||||
|     }, | ||||
| ) | ||||
| _sym_db.RegisterMessage(Restrictions) | ||||
| 
 | ||||
| DESCRIPTOR._options = None | ||||
| # @@protoc_insertion_point(module_scope) | ||||
							
								
								
									
										149
									
								
								resources/lib/librespot/proto/Session_pb2.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										149
									
								
								resources/lib/librespot/proto/Session_pb2.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,149 @@ | |||
| # -*- coding: utf-8 -*- | ||||
| # Generated by the protocol buffer compiler.  DO NOT EDIT! | ||||
| # source: session.proto | ||||
| """Generated protocol buffer code.""" | ||||
| import Context_pb2 as context__pb2 | ||||
| import ContextPlayerOptions_pb2 as context__player__options__pb2 | ||||
| import PlayOrigin_pb2 as play__origin__pb2 | ||||
| from google.protobuf import descriptor as _descriptor | ||||
| from google.protobuf import message as _message | ||||
| from google.protobuf import reflection as _reflection | ||||
| from google.protobuf import symbol_database as _symbol_database | ||||
| 
 | ||||
| # @@protoc_insertion_point(imports) | ||||
| 
 | ||||
| _sym_db = _symbol_database.Default() | ||||
| 
 | ||||
| DESCRIPTOR = _descriptor.FileDescriptor( | ||||
|     name="session.proto", | ||||
|     package="spotify.player.proto.transfer", | ||||
|     syntax="proto2", | ||||
|     serialized_options=b"\n\024com.spotify.transferH\002", | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     serialized_pb= | ||||
|     b'\n\rsession.proto\x12\x1dspotify.player.proto.transfer\x1a\rcontext.proto\x1a\x1c\x63ontext_player_options.proto\x1a\x11play_origin.proto"\xd3\x01\n\x07Session\x12\x35\n\x0bplay_origin\x18\x01 \x01(\x0b\x32 .spotify.player.proto.PlayOrigin\x12.\n\x07\x63ontext\x18\x02 \x01(\x0b\x32\x1d.spotify.player.proto.Context\x12\x13\n\x0b\x63urrent_uid\x18\x03 \x01(\t\x12L\n\x10option_overrides\x18\x04 \x01(\x0b\x32\x32.spotify.player.proto.ContextPlayerOptionOverridesB\x18\n\x14\x63om.spotify.transferH\x02', | ||||
|     dependencies=[ | ||||
|         context__pb2.DESCRIPTOR, | ||||
|         context__player__options__pb2.DESCRIPTOR, | ||||
|         play__origin__pb2.DESCRIPTOR, | ||||
|     ], | ||||
| ) | ||||
| 
 | ||||
| _SESSION = _descriptor.Descriptor( | ||||
|     name="Session", | ||||
|     full_name="spotify.player.proto.transfer.Session", | ||||
|     filename=None, | ||||
|     file=DESCRIPTOR, | ||||
|     containing_type=None, | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     fields=[ | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="play_origin", | ||||
|             full_name="spotify.player.proto.transfer.Session.play_origin", | ||||
|             index=0, | ||||
|             number=1, | ||||
|             type=11, | ||||
|             cpp_type=10, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=None, | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="context", | ||||
|             full_name="spotify.player.proto.transfer.Session.context", | ||||
|             index=1, | ||||
|             number=2, | ||||
|             type=11, | ||||
|             cpp_type=10, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=None, | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="current_uid", | ||||
|             full_name="spotify.player.proto.transfer.Session.current_uid", | ||||
|             index=2, | ||||
|             number=3, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"".decode("utf-8"), | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="option_overrides", | ||||
|             full_name="spotify.player.proto.transfer.Session.option_overrides", | ||||
|             index=3, | ||||
|             number=4, | ||||
|             type=11, | ||||
|             cpp_type=10, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=None, | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|     ], | ||||
|     extensions=[], | ||||
|     nested_types=[], | ||||
|     enum_types=[], | ||||
|     serialized_options=None, | ||||
|     is_extendable=False, | ||||
|     syntax="proto2", | ||||
|     extension_ranges=[], | ||||
|     oneofs=[], | ||||
|     serialized_start=113, | ||||
|     serialized_end=324, | ||||
| ) | ||||
| 
 | ||||
| _SESSION.fields_by_name[ | ||||
|     "play_origin"].message_type = play__origin__pb2._PLAYORIGIN | ||||
| _SESSION.fields_by_name["context"].message_type = context__pb2._CONTEXT | ||||
| _SESSION.fields_by_name[ | ||||
|     "option_overrides"].message_type = context__player__options__pb2._CONTEXTPLAYEROPTIONOVERRIDES | ||||
| DESCRIPTOR.message_types_by_name["Session"] = _SESSION | ||||
| _sym_db.RegisterFileDescriptor(DESCRIPTOR) | ||||
| 
 | ||||
| Session = _reflection.GeneratedProtocolMessageType( | ||||
|     "Session", | ||||
|     (_message.Message, ), | ||||
|     { | ||||
|         "DESCRIPTOR": _SESSION, | ||||
|         "__module__": "session_pb2" | ||||
|         # @@protoc_insertion_point(class_scope:spotify.player.proto.transfer.Session) | ||||
|     }, | ||||
| ) | ||||
| _sym_db.RegisterMessage(Session) | ||||
| 
 | ||||
| DESCRIPTOR._options = None | ||||
| # @@protoc_insertion_point(module_scope) | ||||
							
								
								
									
										154
									
								
								resources/lib/librespot/proto/StorageResolve_pb2.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										154
									
								
								resources/lib/librespot/proto/StorageResolve_pb2.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,154 @@ | |||
| # -*- coding: utf-8 -*- | ||||
| # Generated by the protocol buffer compiler.  DO NOT EDIT! | ||||
| # source: storage-resolve.proto | ||||
| """Generated protocol buffer code.""" | ||||
| from google.protobuf import descriptor as _descriptor | ||||
| from google.protobuf import message as _message | ||||
| from google.protobuf import reflection as _reflection | ||||
| from google.protobuf import symbol_database as _symbol_database | ||||
| # @@protoc_insertion_point(imports) | ||||
| 
 | ||||
| _sym_db = _symbol_database.Default() | ||||
| 
 | ||||
| DESCRIPTOR = _descriptor.FileDescriptor( | ||||
|     name='storage-resolve.proto', | ||||
|     package='spotify.download.proto', | ||||
|     syntax='proto3', | ||||
|     serialized_options=b'\n\023com.spotify.storageH\002', | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     serialized_pb= | ||||
|     b'\n\x15storage-resolve.proto\x12\x16spotify.download.proto\"\xaf\x01\n\x16StorageResolveResponse\x12\x45\n\x06result\x18\x01 \x01(\x0e\x32\x35.spotify.download.proto.StorageResolveResponse.Result\x12\x0e\n\x06\x63\x64nurl\x18\x02 \x03(\t\x12\x0e\n\x06\x66ileid\x18\x04 \x01(\x0c\".\n\x06Result\x12\x07\n\x03\x43\x44N\x10\x00\x12\x0b\n\x07STORAGE\x10\x01\x12\x0e\n\nRESTRICTED\x10\x03\x42\x17\n\x13\x63om.spotify.storageH\x02\x62\x06proto3' | ||||
| ) | ||||
| 
 | ||||
| _STORAGERESOLVERESPONSE_RESULT = _descriptor.EnumDescriptor( | ||||
|     name='Result', | ||||
|     full_name='spotify.download.proto.StorageResolveResponse.Result', | ||||
|     filename=None, | ||||
|     file=DESCRIPTOR, | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     values=[ | ||||
|         _descriptor.EnumValueDescriptor( | ||||
|             name='CDN', | ||||
|             index=0, | ||||
|             number=0, | ||||
|             serialized_options=None, | ||||
|             type=None, | ||||
|             create_key=_descriptor._internal_create_key), | ||||
|         _descriptor.EnumValueDescriptor( | ||||
|             name='STORAGE', | ||||
|             index=1, | ||||
|             number=1, | ||||
|             serialized_options=None, | ||||
|             type=None, | ||||
|             create_key=_descriptor._internal_create_key), | ||||
|         _descriptor.EnumValueDescriptor( | ||||
|             name='RESTRICTED', | ||||
|             index=2, | ||||
|             number=3, | ||||
|             serialized_options=None, | ||||
|             type=None, | ||||
|             create_key=_descriptor._internal_create_key), | ||||
|     ], | ||||
|     containing_type=None, | ||||
|     serialized_options=None, | ||||
|     serialized_start=179, | ||||
|     serialized_end=225, | ||||
| ) | ||||
| _sym_db.RegisterEnumDescriptor(_STORAGERESOLVERESPONSE_RESULT) | ||||
| 
 | ||||
| _STORAGERESOLVERESPONSE = _descriptor.Descriptor( | ||||
|     name='StorageResolveResponse', | ||||
|     full_name='spotify.download.proto.StorageResolveResponse', | ||||
|     filename=None, | ||||
|     file=DESCRIPTOR, | ||||
|     containing_type=None, | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     fields=[ | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name='result', | ||||
|             full_name='spotify.download.proto.StorageResolveResponse.result', | ||||
|             index=0, | ||||
|             number=1, | ||||
|             type=14, | ||||
|             cpp_type=8, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=0, | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name='cdnurl', | ||||
|             full_name='spotify.download.proto.StorageResolveResponse.cdnurl', | ||||
|             index=1, | ||||
|             number=2, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=3, | ||||
|             has_default_value=False, | ||||
|             default_value=[], | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name='fileid', | ||||
|             full_name='spotify.download.proto.StorageResolveResponse.fileid', | ||||
|             index=2, | ||||
|             number=4, | ||||
|             type=12, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"", | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key), | ||||
|     ], | ||||
|     extensions=[], | ||||
|     nested_types=[], | ||||
|     enum_types=[ | ||||
|         _STORAGERESOLVERESPONSE_RESULT, | ||||
|     ], | ||||
|     serialized_options=None, | ||||
|     is_extendable=False, | ||||
|     syntax='proto3', | ||||
|     extension_ranges=[], | ||||
|     oneofs=[], | ||||
|     serialized_start=50, | ||||
|     serialized_end=225, | ||||
| ) | ||||
| 
 | ||||
| _STORAGERESOLVERESPONSE.fields_by_name[ | ||||
|     'result'].enum_type = _STORAGERESOLVERESPONSE_RESULT | ||||
| _STORAGERESOLVERESPONSE_RESULT.containing_type = _STORAGERESOLVERESPONSE | ||||
| DESCRIPTOR.message_types_by_name[ | ||||
|     'StorageResolveResponse'] = _STORAGERESOLVERESPONSE | ||||
| _sym_db.RegisterFileDescriptor(DESCRIPTOR) | ||||
| 
 | ||||
| StorageResolveResponse = _reflection.GeneratedProtocolMessageType( | ||||
|     'StorageResolveResponse', | ||||
|     (_message.Message, ), | ||||
|     { | ||||
|         'DESCRIPTOR': _STORAGERESOLVERESPONSE, | ||||
|         '__module__': 'storage_resolve_pb2' | ||||
|         # @@protoc_insertion_point(class_scope:spotify.download.proto.StorageResolveResponse) | ||||
|     }) | ||||
| _sym_db.RegisterMessage(StorageResolveResponse) | ||||
| 
 | ||||
| DESCRIPTOR._options = None | ||||
| # @@protoc_insertion_point(module_scope) | ||||
							
								
								
									
										174
									
								
								resources/lib/librespot/proto/TransferState_pb2.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										174
									
								
								resources/lib/librespot/proto/TransferState_pb2.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,174 @@ | |||
| # -*- coding: utf-8 -*- | ||||
| # Generated by the protocol buffer compiler.  DO NOT EDIT! | ||||
| # source: transfer_state.proto | ||||
| """Generated protocol buffer code.""" | ||||
| import ContextPlayerOptions_pb2 as context__player__options__pb2 | ||||
| import Playback_pb2 as playback__pb2 | ||||
| import Queue_pb2 as queue__pb2 | ||||
| import Session_pb2 as session__pb2 | ||||
| from google.protobuf import descriptor as _descriptor | ||||
| from google.protobuf import message as _message | ||||
| from google.protobuf import reflection as _reflection | ||||
| from google.protobuf import symbol_database as _symbol_database | ||||
| 
 | ||||
| # @@protoc_insertion_point(imports) | ||||
| 
 | ||||
| _sym_db = _symbol_database.Default() | ||||
| 
 | ||||
| DESCRIPTOR = _descriptor.FileDescriptor( | ||||
|     name="transfer_state.proto", | ||||
|     package="spotify.player.proto.transfer", | ||||
|     syntax="proto2", | ||||
|     serialized_options=b"\n\024com.spotify.transferH\002", | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     serialized_pb= | ||||
|     b"\n\x14transfer_state.proto\x12\x1dspotify.player.proto.transfer\x1a\x1c\x63ontext_player_options.proto\x1a\x0eplayback.proto\x1a\rsession.proto\x1a\x0bqueue.proto\"\x99\x02\n\rTransferState\x12;\n\x07options\x18\x01 \x01(\x0b\x32*.spotify.player.proto.ContextPlayerOptions\x12\x39\n\x08playback\x18\x02 \x01(\x0b\x32'.spotify.player.proto.transfer.Playback\x12?\n\x0f\x63urrent_session\x18\x03 \x01(\x0b\x32&.spotify.player.proto.transfer.Session\x12\x33\n\x05queue\x18\x04 \x01(\x0b\x32$.spotify.player.proto.transfer.Queue\x12\x1a\n\x12\x63reation_timestamp\x18\x05 \x01(\x03\x42\x18\n\x14\x63om.spotify.transferH\x02", | ||||
|     dependencies=[ | ||||
|         context__player__options__pb2.DESCRIPTOR, | ||||
|         playback__pb2.DESCRIPTOR, | ||||
|         session__pb2.DESCRIPTOR, | ||||
|         queue__pb2.DESCRIPTOR, | ||||
|     ], | ||||
| ) | ||||
| 
 | ||||
| _TRANSFERSTATE = _descriptor.Descriptor( | ||||
|     name="TransferState", | ||||
|     full_name="spotify.player.proto.transfer.TransferState", | ||||
|     filename=None, | ||||
|     file=DESCRIPTOR, | ||||
|     containing_type=None, | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     fields=[ | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="options", | ||||
|             full_name="spotify.player.proto.transfer.TransferState.options", | ||||
|             index=0, | ||||
|             number=1, | ||||
|             type=11, | ||||
|             cpp_type=10, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=None, | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="playback", | ||||
|             full_name="spotify.player.proto.transfer.TransferState.playback", | ||||
|             index=1, | ||||
|             number=2, | ||||
|             type=11, | ||||
|             cpp_type=10, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=None, | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="current_session", | ||||
|             full_name= | ||||
|             "spotify.player.proto.transfer.TransferState.current_session", | ||||
|             index=2, | ||||
|             number=3, | ||||
|             type=11, | ||||
|             cpp_type=10, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=None, | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="queue", | ||||
|             full_name="spotify.player.proto.transfer.TransferState.queue", | ||||
|             index=3, | ||||
|             number=4, | ||||
|             type=11, | ||||
|             cpp_type=10, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=None, | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="creation_timestamp", | ||||
|             full_name= | ||||
|             "spotify.player.proto.transfer.TransferState.creation_timestamp", | ||||
|             index=4, | ||||
|             number=5, | ||||
|             type=3, | ||||
|             cpp_type=2, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=0, | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|     ], | ||||
|     extensions=[], | ||||
|     nested_types=[], | ||||
|     enum_types=[], | ||||
|     serialized_options=None, | ||||
|     is_extendable=False, | ||||
|     syntax="proto2", | ||||
|     extension_ranges=[], | ||||
|     oneofs=[], | ||||
|     serialized_start=130, | ||||
|     serialized_end=411, | ||||
| ) | ||||
| 
 | ||||
| _TRANSFERSTATE.fields_by_name[ | ||||
|     "options"].message_type = context__player__options__pb2._CONTEXTPLAYEROPTIONS | ||||
| _TRANSFERSTATE.fields_by_name[ | ||||
|     "playback"].message_type = playback__pb2._PLAYBACK | ||||
| _TRANSFERSTATE.fields_by_name[ | ||||
|     "current_session"].message_type = session__pb2._SESSION | ||||
| _TRANSFERSTATE.fields_by_name["queue"].message_type = queue__pb2._QUEUE | ||||
| DESCRIPTOR.message_types_by_name["TransferState"] = _TRANSFERSTATE | ||||
| _sym_db.RegisterFileDescriptor(DESCRIPTOR) | ||||
| 
 | ||||
| TransferState = _reflection.GeneratedProtocolMessageType( | ||||
|     "TransferState", | ||||
|     (_message.Message, ), | ||||
|     { | ||||
|         "DESCRIPTOR": _TRANSFERSTATE, | ||||
|         "__module__": "transfer_state_pb2" | ||||
|         # @@protoc_insertion_point(class_scope:spotify.player.proto.transfer.TransferState) | ||||
|     }, | ||||
| ) | ||||
| _sym_db.RegisterMessage(TransferState) | ||||
| 
 | ||||
| DESCRIPTOR._options = None | ||||
| # @@protoc_insertion_point(module_scope) | ||||
							
								
								
									
										0
									
								
								resources/lib/librespot/proto/__init__.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								resources/lib/librespot/proto/__init__.py
									
										
									
									
									
										Normal file
									
								
							
							
								
								
									
										0
									
								
								resources/lib/librespot/proto/spotify/__init__.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								resources/lib/librespot/proto/spotify/__init__.py
									
										
									
									
									
										Normal file
									
								
							
							
								
								
									
										0
									
								
								resources/lib/librespot/proto/spotify/login5/__init__.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								resources/lib/librespot/proto/spotify/login5/__init__.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,98 @@ | |||
| # -*- coding: utf-8 -*- | ||||
| # Generated by the protocol buffer compiler.  DO NOT EDIT! | ||||
| # source: spotify/login5/v3/client_info.proto | ||||
| """Generated protocol buffer code.""" | ||||
| from google.protobuf import descriptor as _descriptor | ||||
| from google.protobuf import message as _message | ||||
| from google.protobuf import reflection as _reflection | ||||
| from google.protobuf import symbol_database as _symbol_database | ||||
| 
 | ||||
| # @@protoc_insertion_point(imports) | ||||
| 
 | ||||
| _sym_db = _symbol_database.Default() | ||||
| 
 | ||||
| DESCRIPTOR = _descriptor.FileDescriptor( | ||||
|     name="spotify/login5/v3/client_info.proto", | ||||
|     package="spotify.login5.v3", | ||||
|     syntax="proto3", | ||||
|     serialized_options=b"\n\024com.spotify.login5v3", | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     serialized_pb= | ||||
|     b'\n#spotify/login5/v3/client_info.proto\x12\x11spotify.login5.v3"2\n\nClientInfo\x12\x11\n\tclient_id\x18\x01 \x01(\t\x12\x11\n\tdevice_id\x18\x02 \x01(\tB\x16\n\x14\x63om.spotify.login5v3b\x06proto3', | ||||
| ) | ||||
| 
 | ||||
| _CLIENTINFO = _descriptor.Descriptor( | ||||
|     name="ClientInfo", | ||||
|     full_name="spotify.login5.v3.ClientInfo", | ||||
|     filename=None, | ||||
|     file=DESCRIPTOR, | ||||
|     containing_type=None, | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     fields=[ | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="client_id", | ||||
|             full_name="spotify.login5.v3.ClientInfo.client_id", | ||||
|             index=0, | ||||
|             number=1, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"".decode("utf-8"), | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="device_id", | ||||
|             full_name="spotify.login5.v3.ClientInfo.device_id", | ||||
|             index=1, | ||||
|             number=2, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"".decode("utf-8"), | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|     ], | ||||
|     extensions=[], | ||||
|     nested_types=[], | ||||
|     enum_types=[], | ||||
|     serialized_options=None, | ||||
|     is_extendable=False, | ||||
|     syntax="proto3", | ||||
|     extension_ranges=[], | ||||
|     oneofs=[], | ||||
|     serialized_start=58, | ||||
|     serialized_end=108, | ||||
| ) | ||||
| 
 | ||||
| DESCRIPTOR.message_types_by_name["ClientInfo"] = _CLIENTINFO | ||||
| _sym_db.RegisterFileDescriptor(DESCRIPTOR) | ||||
| 
 | ||||
| ClientInfo = _reflection.GeneratedProtocolMessageType( | ||||
|     "ClientInfo", | ||||
|     (_message.Message, ), | ||||
|     { | ||||
|         "DESCRIPTOR": _CLIENTINFO, | ||||
|         "__module__": "spotify.login5.v3.client_info_pb2" | ||||
|         # @@protoc_insertion_point(class_scope:spotify.login5.v3.ClientInfo) | ||||
|     }, | ||||
| ) | ||||
| _sym_db.RegisterMessage(ClientInfo) | ||||
| 
 | ||||
| DESCRIPTOR._options = None | ||||
| # @@protoc_insertion_point(module_scope) | ||||
							
								
								
									
										972
									
								
								resources/lib/librespot/proto/spotify/login5/v3/Login5_pb2.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										972
									
								
								resources/lib/librespot/proto/spotify/login5/v3/Login5_pb2.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,972 @@ | |||
| # -*- coding: utf-8 -*- | ||||
| # Generated by the protocol buffer compiler.  DO NOT EDIT! | ||||
| # source: spotify/login5/v3/login5.proto | ||||
| """Generated protocol buffer code.""" | ||||
| from google.protobuf import descriptor as _descriptor | ||||
| from google.protobuf import message as _message | ||||
| from google.protobuf import reflection as _reflection | ||||
| from google.protobuf import symbol_database as _symbol_database | ||||
| from google.protobuf.internal import enum_type_wrapper | ||||
| from spotify.login5.v3 import \ | ||||
|     client_info_pb2 as spotify_dot_login5_dot_v3_dot_client__info__pb2 | ||||
| from spotify.login5.v3 import \ | ||||
|     user_info_pb2 as spotify_dot_login5_dot_v3_dot_user__info__pb2 | ||||
| from spotify.login5.v3.challenges import \ | ||||
|     code_pb2 as spotify_dot_login5_dot_v3_dot_challenges_dot_code__pb2 | ||||
| from spotify.login5.v3.challenges import \ | ||||
|     hashcash_pb2 as spotify_dot_login5_dot_v3_dot_challenges_dot_hashcash__pb2 | ||||
| from spotify.login5.v3.credentials import \ | ||||
|     credentials_pb2 as \ | ||||
|     spotify_dot_login5_dot_v3_dot_credentials_dot_credentials__pb2 | ||||
| from spotify.login5.v3.identifiers import \ | ||||
|     identifiers_pb2 as \ | ||||
|     spotify_dot_login5_dot_v3_dot_identifiers_dot_identifiers__pb2 | ||||
| 
 | ||||
| # @@protoc_insertion_point(imports) | ||||
| 
 | ||||
| _sym_db = _symbol_database.Default() | ||||
| 
 | ||||
| DESCRIPTOR = _descriptor.FileDescriptor( | ||||
|     name="spotify/login5/v3/login5.proto", | ||||
|     package="spotify.login5.v3", | ||||
|     syntax="proto3", | ||||
|     serialized_options=b"\n\024com.spotify.login5v3", | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     serialized_pb= | ||||
|     b'\n\x1espotify/login5/v3/login5.proto\x12\x11spotify.login5.v3\x1a#spotify/login5/v3/client_info.proto\x1a!spotify/login5/v3/user_info.proto\x1a\'spotify/login5/v3/challenges/code.proto\x1a+spotify/login5/v3/challenges/hashcash.proto\x1a/spotify/login5/v3/credentials/credentials.proto\x1a/spotify/login5/v3/identifiers/identifiers.proto">\n\nChallenges\x12\x30\n\nchallenges\x18\x01 \x03(\x0b\x32\x1c.spotify.login5.v3.Challenge"\x89\x01\n\tChallenge\x12\x41\n\x08hashcash\x18\x01 \x01(\x0b\x32/.spotify.login5.v3.challenges.HashcashChallenge\x12\x39\n\x04\x63ode\x18\x02 \x01(\x0b\x32+.spotify.login5.v3.challenges.CodeChallenge"M\n\x12\x43hallengeSolutions\x12\x37\n\tsolutions\x18\x01 \x03(\x0b\x32$.spotify.login5.v3.ChallengeSolution"\x8f\x01\n\x11\x43hallengeSolution\x12@\n\x08hashcash\x18\x01 \x01(\x0b\x32..spotify.login5.v3.challenges.HashcashSolution\x12\x38\n\x04\x63ode\x18\x02 \x01(\x0b\x32*.spotify.login5.v3.challenges.CodeSolution"\xad\x05\n\x0cLoginRequest\x12\x32\n\x0b\x63lient_info\x18\x01 \x01(\x0b\x32\x1d.spotify.login5.v3.ClientInfo\x12\x15\n\rlogin_context\x18\x02 \x01(\x0c\x12\x42\n\x13\x63hallenge_solutions\x18\x03 \x01(\x0b\x32%.spotify.login5.v3.ChallengeSolutions\x12J\n\x11stored_credential\x18\x64 \x01(\x0b\x32/.spotify.login5.v3.credentials.StoredCredential\x12\x39\n\x08password\x18\x65 \x01(\x0b\x32\'.spotify.login5.v3.credentials.Password\x12Q\n\x15\x66\x61\x63\x65\x62ook_access_token\x18\x66 \x01(\x0b\x32\x32.spotify.login5.v3.credentials.FacebookAccessToken\x12@\n\x0cphone_number\x18g \x01(\x0b\x32*.spotify.login5.v3.identifiers.PhoneNumber\x12\x43\n\x0eone_time_token\x18h \x01(\x0b\x32+.spotify.login5.v3.credentials.OneTimeToken\x12U\n\x17parent_child_credential\x18i \x01(\x0b\x32\x34.spotify.login5.v3.credentials.ParentChildCredential\x12V\n\x18\x61pple_sign_in_credential\x18j \x01(\x0b\x32\x34.spotify.login5.v3.credentials.AppleSignInCredential"m\n\x07LoginOk\x12\x10\n\x08username\x18\x01 \x01(\t\x12\x14\n\x0c\x61\x63\x63\x65ss_token\x18\x02 \x01(\t\x12\x19\n\x11stored_credential\x18\x03 \x01(\x0c\x12\x1f\n\x17\x61\x63\x63\x65ss_token_expires_in\x18\x04 \x01(\x05"\xf8\x02\n\rLoginResponse\x12&\n\x02ok\x18\x01 \x01(\x0b\x32\x1a.spotify.login5.v3.LoginOk\x12,\n\x05\x65rror\x18\x02 \x01(\x0e\x32\x1d.spotify.login5.v3.LoginError\x12\x31\n\nchallenges\x18\x03 \x01(\x0b\x32\x1d.spotify.login5.v3.Challenges\x12;\n\x08warnings\x18\x04 \x03(\x0e\x32).spotify.login5.v3.LoginResponse.Warnings\x12\x15\n\rlogin_context\x18\x05 \x01(\x0c\x12\x18\n\x10identifier_token\x18\x06 \x01(\t\x12.\n\tuser_info\x18\x07 \x01(\x0b\x32\x1b.spotify.login5.v3.UserInfo"@\n\x08Warnings\x12\x13\n\x0fUNKNOWN_WARNING\x10\x00\x12\x1f\n\x1b\x44\x45PRECATED_PROTOCOL_VERSION\x10\x01*\xd3\x01\n\nLoginError\x12\x11\n\rUNKNOWN_ERROR\x10\x00\x12\x17\n\x13INVALID_CREDENTIALS\x10\x01\x12\x0f\n\x0b\x42\x41\x44_REQUEST\x10\x02\x12\x1e\n\x1aUNSUPPORTED_LOGIN_PROTOCOL\x10\x03\x12\x0b\n\x07TIMEOUT\x10\x04\x12\x16\n\x12UNKNOWN_IDENTIFIER\x10\x05\x12\x15\n\x11TOO_MANY_ATTEMPTS\x10\x06\x12\x17\n\x13INVALID_PHONENUMBER\x10\x07\x12\x13\n\x0fTRY_AGAIN_LATER\x10\x08\x42\x16\n\x14\x63om.spotify.login5v3b\x06proto3', | ||||
|     dependencies=[ | ||||
|         spotify_dot_login5_dot_v3_dot_client__info__pb2.DESCRIPTOR, | ||||
|         spotify_dot_login5_dot_v3_dot_user__info__pb2.DESCRIPTOR, | ||||
|         spotify_dot_login5_dot_v3_dot_challenges_dot_code__pb2.DESCRIPTOR, | ||||
|         spotify_dot_login5_dot_v3_dot_challenges_dot_hashcash__pb2.DESCRIPTOR, | ||||
|         spotify_dot_login5_dot_v3_dot_credentials_dot_credentials__pb2. | ||||
|         DESCRIPTOR, | ||||
|         spotify_dot_login5_dot_v3_dot_identifiers_dot_identifiers__pb2. | ||||
|         DESCRIPTOR, | ||||
|     ], | ||||
| ) | ||||
| 
 | ||||
| _LOGINERROR = _descriptor.EnumDescriptor( | ||||
|     name="LoginError", | ||||
|     full_name="spotify.login5.v3.LoginError", | ||||
|     filename=None, | ||||
|     file=DESCRIPTOR, | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     values=[ | ||||
|         _descriptor.EnumValueDescriptor( | ||||
|             name="UNKNOWN_ERROR", | ||||
|             index=0, | ||||
|             number=0, | ||||
|             serialized_options=None, | ||||
|             type=None, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.EnumValueDescriptor( | ||||
|             name="INVALID_CREDENTIALS", | ||||
|             index=1, | ||||
|             number=1, | ||||
|             serialized_options=None, | ||||
|             type=None, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.EnumValueDescriptor( | ||||
|             name="BAD_REQUEST", | ||||
|             index=2, | ||||
|             number=2, | ||||
|             serialized_options=None, | ||||
|             type=None, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.EnumValueDescriptor( | ||||
|             name="UNSUPPORTED_LOGIN_PROTOCOL", | ||||
|             index=3, | ||||
|             number=3, | ||||
|             serialized_options=None, | ||||
|             type=None, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.EnumValueDescriptor( | ||||
|             name="TIMEOUT", | ||||
|             index=4, | ||||
|             number=4, | ||||
|             serialized_options=None, | ||||
|             type=None, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.EnumValueDescriptor( | ||||
|             name="UNKNOWN_IDENTIFIER", | ||||
|             index=5, | ||||
|             number=5, | ||||
|             serialized_options=None, | ||||
|             type=None, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.EnumValueDescriptor( | ||||
|             name="TOO_MANY_ATTEMPTS", | ||||
|             index=6, | ||||
|             number=6, | ||||
|             serialized_options=None, | ||||
|             type=None, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.EnumValueDescriptor( | ||||
|             name="INVALID_PHONENUMBER", | ||||
|             index=7, | ||||
|             number=7, | ||||
|             serialized_options=None, | ||||
|             type=None, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.EnumValueDescriptor( | ||||
|             name="TRY_AGAIN_LATER", | ||||
|             index=8, | ||||
|             number=8, | ||||
|             serialized_options=None, | ||||
|             type=None, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|     ], | ||||
|     containing_type=None, | ||||
|     serialized_options=None, | ||||
|     serialized_start=1917, | ||||
|     serialized_end=2128, | ||||
| ) | ||||
| _sym_db.RegisterEnumDescriptor(_LOGINERROR) | ||||
| 
 | ||||
| LoginError = enum_type_wrapper.EnumTypeWrapper(_LOGINERROR) | ||||
| UNKNOWN_ERROR = 0 | ||||
| INVALID_CREDENTIALS = 1 | ||||
| BAD_REQUEST = 2 | ||||
| UNSUPPORTED_LOGIN_PROTOCOL = 3 | ||||
| TIMEOUT = 4 | ||||
| UNKNOWN_IDENTIFIER = 5 | ||||
| TOO_MANY_ATTEMPTS = 6 | ||||
| INVALID_PHONENUMBER = 7 | ||||
| TRY_AGAIN_LATER = 8 | ||||
| 
 | ||||
| _LOGINRESPONSE_WARNINGS = _descriptor.EnumDescriptor( | ||||
|     name="Warnings", | ||||
|     full_name="spotify.login5.v3.LoginResponse.Warnings", | ||||
|     filename=None, | ||||
|     file=DESCRIPTOR, | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     values=[ | ||||
|         _descriptor.EnumValueDescriptor( | ||||
|             name="UNKNOWN_WARNING", | ||||
|             index=0, | ||||
|             number=0, | ||||
|             serialized_options=None, | ||||
|             type=None, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.EnumValueDescriptor( | ||||
|             name="DEPRECATED_PROTOCOL_VERSION", | ||||
|             index=1, | ||||
|             number=1, | ||||
|             serialized_options=None, | ||||
|             type=None, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|     ], | ||||
|     containing_type=None, | ||||
|     serialized_options=None, | ||||
|     serialized_start=1850, | ||||
|     serialized_end=1914, | ||||
| ) | ||||
| _sym_db.RegisterEnumDescriptor(_LOGINRESPONSE_WARNINGS) | ||||
| 
 | ||||
| _CHALLENGES = _descriptor.Descriptor( | ||||
|     name="Challenges", | ||||
|     full_name="spotify.login5.v3.Challenges", | ||||
|     filename=None, | ||||
|     file=DESCRIPTOR, | ||||
|     containing_type=None, | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     fields=[ | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="challenges", | ||||
|             full_name="spotify.login5.v3.Challenges.challenges", | ||||
|             index=0, | ||||
|             number=1, | ||||
|             type=11, | ||||
|             cpp_type=10, | ||||
|             label=3, | ||||
|             has_default_value=False, | ||||
|             default_value=[], | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|     ], | ||||
|     extensions=[], | ||||
|     nested_types=[], | ||||
|     enum_types=[], | ||||
|     serialized_options=None, | ||||
|     is_extendable=False, | ||||
|     syntax="proto3", | ||||
|     extension_ranges=[], | ||||
|     oneofs=[], | ||||
|     serialized_start=309, | ||||
|     serialized_end=371, | ||||
| ) | ||||
| 
 | ||||
| _CHALLENGE = _descriptor.Descriptor( | ||||
|     name="Challenge", | ||||
|     full_name="spotify.login5.v3.Challenge", | ||||
|     filename=None, | ||||
|     file=DESCRIPTOR, | ||||
|     containing_type=None, | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     fields=[ | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="hashcash", | ||||
|             full_name="spotify.login5.v3.Challenge.hashcash", | ||||
|             index=0, | ||||
|             number=1, | ||||
|             type=11, | ||||
|             cpp_type=10, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=None, | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="code", | ||||
|             full_name="spotify.login5.v3.Challenge.code", | ||||
|             index=1, | ||||
|             number=2, | ||||
|             type=11, | ||||
|             cpp_type=10, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=None, | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|     ], | ||||
|     extensions=[], | ||||
|     nested_types=[], | ||||
|     enum_types=[], | ||||
|     serialized_options=None, | ||||
|     is_extendable=False, | ||||
|     syntax="proto3", | ||||
|     extension_ranges=[], | ||||
|     oneofs=[], | ||||
|     serialized_start=374, | ||||
|     serialized_end=511, | ||||
| ) | ||||
| 
 | ||||
| _CHALLENGESOLUTIONS = _descriptor.Descriptor( | ||||
|     name="ChallengeSolutions", | ||||
|     full_name="spotify.login5.v3.ChallengeSolutions", | ||||
|     filename=None, | ||||
|     file=DESCRIPTOR, | ||||
|     containing_type=None, | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     fields=[ | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="solutions", | ||||
|             full_name="spotify.login5.v3.ChallengeSolutions.solutions", | ||||
|             index=0, | ||||
|             number=1, | ||||
|             type=11, | ||||
|             cpp_type=10, | ||||
|             label=3, | ||||
|             has_default_value=False, | ||||
|             default_value=[], | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|     ], | ||||
|     extensions=[], | ||||
|     nested_types=[], | ||||
|     enum_types=[], | ||||
|     serialized_options=None, | ||||
|     is_extendable=False, | ||||
|     syntax="proto3", | ||||
|     extension_ranges=[], | ||||
|     oneofs=[], | ||||
|     serialized_start=513, | ||||
|     serialized_end=590, | ||||
| ) | ||||
| 
 | ||||
| _CHALLENGESOLUTION = _descriptor.Descriptor( | ||||
|     name="ChallengeSolution", | ||||
|     full_name="spotify.login5.v3.ChallengeSolution", | ||||
|     filename=None, | ||||
|     file=DESCRIPTOR, | ||||
|     containing_type=None, | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     fields=[ | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="hashcash", | ||||
|             full_name="spotify.login5.v3.ChallengeSolution.hashcash", | ||||
|             index=0, | ||||
|             number=1, | ||||
|             type=11, | ||||
|             cpp_type=10, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=None, | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="code", | ||||
|             full_name="spotify.login5.v3.ChallengeSolution.code", | ||||
|             index=1, | ||||
|             number=2, | ||||
|             type=11, | ||||
|             cpp_type=10, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=None, | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|     ], | ||||
|     extensions=[], | ||||
|     nested_types=[], | ||||
|     enum_types=[], | ||||
|     serialized_options=None, | ||||
|     is_extendable=False, | ||||
|     syntax="proto3", | ||||
|     extension_ranges=[], | ||||
|     oneofs=[], | ||||
|     serialized_start=593, | ||||
|     serialized_end=736, | ||||
| ) | ||||
| 
 | ||||
| _LOGINREQUEST = _descriptor.Descriptor( | ||||
|     name="LoginRequest", | ||||
|     full_name="spotify.login5.v3.LoginRequest", | ||||
|     filename=None, | ||||
|     file=DESCRIPTOR, | ||||
|     containing_type=None, | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     fields=[ | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="client_info", | ||||
|             full_name="spotify.login5.v3.LoginRequest.client_info", | ||||
|             index=0, | ||||
|             number=1, | ||||
|             type=11, | ||||
|             cpp_type=10, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=None, | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="login_context", | ||||
|             full_name="spotify.login5.v3.LoginRequest.login_context", | ||||
|             index=1, | ||||
|             number=2, | ||||
|             type=12, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"", | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="challenge_solutions", | ||||
|             full_name="spotify.login5.v3.LoginRequest.challenge_solutions", | ||||
|             index=2, | ||||
|             number=3, | ||||
|             type=11, | ||||
|             cpp_type=10, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=None, | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="stored_credential", | ||||
|             full_name="spotify.login5.v3.LoginRequest.stored_credential", | ||||
|             index=3, | ||||
|             number=100, | ||||
|             type=11, | ||||
|             cpp_type=10, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=None, | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="password", | ||||
|             full_name="spotify.login5.v3.LoginRequest.password", | ||||
|             index=4, | ||||
|             number=101, | ||||
|             type=11, | ||||
|             cpp_type=10, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=None, | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="facebook_access_token", | ||||
|             full_name="spotify.login5.v3.LoginRequest.facebook_access_token", | ||||
|             index=5, | ||||
|             number=102, | ||||
|             type=11, | ||||
|             cpp_type=10, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=None, | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="phone_number", | ||||
|             full_name="spotify.login5.v3.LoginRequest.phone_number", | ||||
|             index=6, | ||||
|             number=103, | ||||
|             type=11, | ||||
|             cpp_type=10, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=None, | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="one_time_token", | ||||
|             full_name="spotify.login5.v3.LoginRequest.one_time_token", | ||||
|             index=7, | ||||
|             number=104, | ||||
|             type=11, | ||||
|             cpp_type=10, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=None, | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="parent_child_credential", | ||||
|             full_name="spotify.login5.v3.LoginRequest.parent_child_credential", | ||||
|             index=8, | ||||
|             number=105, | ||||
|             type=11, | ||||
|             cpp_type=10, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=None, | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="apple_sign_in_credential", | ||||
|             full_name="spotify.login5.v3.LoginRequest.apple_sign_in_credential", | ||||
|             index=9, | ||||
|             number=106, | ||||
|             type=11, | ||||
|             cpp_type=10, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=None, | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|     ], | ||||
|     extensions=[], | ||||
|     nested_types=[], | ||||
|     enum_types=[], | ||||
|     serialized_options=None, | ||||
|     is_extendable=False, | ||||
|     syntax="proto3", | ||||
|     extension_ranges=[], | ||||
|     oneofs=[], | ||||
|     serialized_start=739, | ||||
|     serialized_end=1424, | ||||
| ) | ||||
| 
 | ||||
| _LOGINOK = _descriptor.Descriptor( | ||||
|     name="LoginOk", | ||||
|     full_name="spotify.login5.v3.LoginOk", | ||||
|     filename=None, | ||||
|     file=DESCRIPTOR, | ||||
|     containing_type=None, | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     fields=[ | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="username", | ||||
|             full_name="spotify.login5.v3.LoginOk.username", | ||||
|             index=0, | ||||
|             number=1, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"".decode("utf-8"), | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="access_token", | ||||
|             full_name="spotify.login5.v3.LoginOk.access_token", | ||||
|             index=1, | ||||
|             number=2, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"".decode("utf-8"), | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="stored_credential", | ||||
|             full_name="spotify.login5.v3.LoginOk.stored_credential", | ||||
|             index=2, | ||||
|             number=3, | ||||
|             type=12, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"", | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="access_token_expires_in", | ||||
|             full_name="spotify.login5.v3.LoginOk.access_token_expires_in", | ||||
|             index=3, | ||||
|             number=4, | ||||
|             type=5, | ||||
|             cpp_type=1, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=0, | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|     ], | ||||
|     extensions=[], | ||||
|     nested_types=[], | ||||
|     enum_types=[], | ||||
|     serialized_options=None, | ||||
|     is_extendable=False, | ||||
|     syntax="proto3", | ||||
|     extension_ranges=[], | ||||
|     oneofs=[], | ||||
|     serialized_start=1426, | ||||
|     serialized_end=1535, | ||||
| ) | ||||
| 
 | ||||
| _LOGINRESPONSE = _descriptor.Descriptor( | ||||
|     name="LoginResponse", | ||||
|     full_name="spotify.login5.v3.LoginResponse", | ||||
|     filename=None, | ||||
|     file=DESCRIPTOR, | ||||
|     containing_type=None, | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     fields=[ | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="ok", | ||||
|             full_name="spotify.login5.v3.LoginResponse.ok", | ||||
|             index=0, | ||||
|             number=1, | ||||
|             type=11, | ||||
|             cpp_type=10, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=None, | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="error", | ||||
|             full_name="spotify.login5.v3.LoginResponse.error", | ||||
|             index=1, | ||||
|             number=2, | ||||
|             type=14, | ||||
|             cpp_type=8, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=0, | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="challenges", | ||||
|             full_name="spotify.login5.v3.LoginResponse.challenges", | ||||
|             index=2, | ||||
|             number=3, | ||||
|             type=11, | ||||
|             cpp_type=10, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=None, | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="warnings", | ||||
|             full_name="spotify.login5.v3.LoginResponse.warnings", | ||||
|             index=3, | ||||
|             number=4, | ||||
|             type=14, | ||||
|             cpp_type=8, | ||||
|             label=3, | ||||
|             has_default_value=False, | ||||
|             default_value=[], | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="login_context", | ||||
|             full_name="spotify.login5.v3.LoginResponse.login_context", | ||||
|             index=4, | ||||
|             number=5, | ||||
|             type=12, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"", | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="identifier_token", | ||||
|             full_name="spotify.login5.v3.LoginResponse.identifier_token", | ||||
|             index=5, | ||||
|             number=6, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"".decode("utf-8"), | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="user_info", | ||||
|             full_name="spotify.login5.v3.LoginResponse.user_info", | ||||
|             index=6, | ||||
|             number=7, | ||||
|             type=11, | ||||
|             cpp_type=10, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=None, | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|     ], | ||||
|     extensions=[], | ||||
|     nested_types=[], | ||||
|     enum_types=[ | ||||
|         _LOGINRESPONSE_WARNINGS, | ||||
|     ], | ||||
|     serialized_options=None, | ||||
|     is_extendable=False, | ||||
|     syntax="proto3", | ||||
|     extension_ranges=[], | ||||
|     oneofs=[], | ||||
|     serialized_start=1538, | ||||
|     serialized_end=1914, | ||||
| ) | ||||
| 
 | ||||
| _CHALLENGES.fields_by_name["challenges"].message_type = _CHALLENGE | ||||
| _CHALLENGE.fields_by_name["hashcash"].message_type = ( | ||||
|     spotify_dot_login5_dot_v3_dot_challenges_dot_hashcash__pb2. | ||||
|     _HASHCASHCHALLENGE) | ||||
| _CHALLENGE.fields_by_name[ | ||||
|     "code"].message_type = spotify_dot_login5_dot_v3_dot_challenges_dot_code__pb2._CODECHALLENGE | ||||
| _CHALLENGESOLUTIONS.fields_by_name[ | ||||
|     "solutions"].message_type = _CHALLENGESOLUTION | ||||
| _CHALLENGESOLUTION.fields_by_name["hashcash"].message_type = ( | ||||
|     spotify_dot_login5_dot_v3_dot_challenges_dot_hashcash__pb2. | ||||
|     _HASHCASHSOLUTION) | ||||
| _CHALLENGESOLUTION.fields_by_name[ | ||||
|     "code"].message_type = spotify_dot_login5_dot_v3_dot_challenges_dot_code__pb2._CODESOLUTION | ||||
| _LOGINREQUEST.fields_by_name[ | ||||
|     "client_info"].message_type = spotify_dot_login5_dot_v3_dot_client__info__pb2._CLIENTINFO | ||||
| _LOGINREQUEST.fields_by_name[ | ||||
|     "challenge_solutions"].message_type = _CHALLENGESOLUTIONS | ||||
| _LOGINREQUEST.fields_by_name["stored_credential"].message_type = ( | ||||
|     spotify_dot_login5_dot_v3_dot_credentials_dot_credentials__pb2. | ||||
|     _STOREDCREDENTIAL) | ||||
| _LOGINREQUEST.fields_by_name["password"].message_type = ( | ||||
|     spotify_dot_login5_dot_v3_dot_credentials_dot_credentials__pb2._PASSWORD) | ||||
| _LOGINREQUEST.fields_by_name["facebook_access_token"].message_type = ( | ||||
|     spotify_dot_login5_dot_v3_dot_credentials_dot_credentials__pb2. | ||||
|     _FACEBOOKACCESSTOKEN) | ||||
| _LOGINREQUEST.fields_by_name["phone_number"].message_type = ( | ||||
|     spotify_dot_login5_dot_v3_dot_identifiers_dot_identifiers__pb2._PHONENUMBER | ||||
| ) | ||||
| _LOGINREQUEST.fields_by_name["one_time_token"].message_type = ( | ||||
|     spotify_dot_login5_dot_v3_dot_credentials_dot_credentials__pb2. | ||||
|     _ONETIMETOKEN) | ||||
| _LOGINREQUEST.fields_by_name["parent_child_credential"].message_type = ( | ||||
|     spotify_dot_login5_dot_v3_dot_credentials_dot_credentials__pb2. | ||||
|     _PARENTCHILDCREDENTIAL) | ||||
| _LOGINREQUEST.fields_by_name["apple_sign_in_credential"].message_type = ( | ||||
|     spotify_dot_login5_dot_v3_dot_credentials_dot_credentials__pb2. | ||||
|     _APPLESIGNINCREDENTIAL) | ||||
| _LOGINRESPONSE.fields_by_name["ok"].message_type = _LOGINOK | ||||
| _LOGINRESPONSE.fields_by_name["error"].enum_type = _LOGINERROR | ||||
| _LOGINRESPONSE.fields_by_name["challenges"].message_type = _CHALLENGES | ||||
| _LOGINRESPONSE.fields_by_name["warnings"].enum_type = _LOGINRESPONSE_WARNINGS | ||||
| _LOGINRESPONSE.fields_by_name[ | ||||
|     "user_info"].message_type = spotify_dot_login5_dot_v3_dot_user__info__pb2._USERINFO | ||||
| _LOGINRESPONSE_WARNINGS.containing_type = _LOGINRESPONSE | ||||
| DESCRIPTOR.message_types_by_name["Challenges"] = _CHALLENGES | ||||
| DESCRIPTOR.message_types_by_name["Challenge"] = _CHALLENGE | ||||
| DESCRIPTOR.message_types_by_name["ChallengeSolutions"] = _CHALLENGESOLUTIONS | ||||
| DESCRIPTOR.message_types_by_name["ChallengeSolution"] = _CHALLENGESOLUTION | ||||
| DESCRIPTOR.message_types_by_name["LoginRequest"] = _LOGINREQUEST | ||||
| DESCRIPTOR.message_types_by_name["LoginOk"] = _LOGINOK | ||||
| DESCRIPTOR.message_types_by_name["LoginResponse"] = _LOGINRESPONSE | ||||
| DESCRIPTOR.enum_types_by_name["LoginError"] = _LOGINERROR | ||||
| _sym_db.RegisterFileDescriptor(DESCRIPTOR) | ||||
| 
 | ||||
| Challenges = _reflection.GeneratedProtocolMessageType( | ||||
|     "Challenges", | ||||
|     (_message.Message, ), | ||||
|     { | ||||
|         "DESCRIPTOR": _CHALLENGES, | ||||
|         "__module__": "spotify.login5.v3.login5_pb2" | ||||
|         # @@protoc_insertion_point(class_scope:spotify.login5.v3.Challenges) | ||||
|     }, | ||||
| ) | ||||
| _sym_db.RegisterMessage(Challenges) | ||||
| 
 | ||||
| Challenge = _reflection.GeneratedProtocolMessageType( | ||||
|     "Challenge", | ||||
|     (_message.Message, ), | ||||
|     { | ||||
|         "DESCRIPTOR": _CHALLENGE, | ||||
|         "__module__": "spotify.login5.v3.login5_pb2" | ||||
|         # @@protoc_insertion_point(class_scope:spotify.login5.v3.Challenge) | ||||
|     }, | ||||
| ) | ||||
| _sym_db.RegisterMessage(Challenge) | ||||
| 
 | ||||
| ChallengeSolutions = _reflection.GeneratedProtocolMessageType( | ||||
|     "ChallengeSolutions", | ||||
|     (_message.Message, ), | ||||
|     { | ||||
|         "DESCRIPTOR": _CHALLENGESOLUTIONS, | ||||
|         "__module__": "spotify.login5.v3.login5_pb2" | ||||
|         # @@protoc_insertion_point(class_scope:spotify.login5.v3.ChallengeSolutions) | ||||
|     }, | ||||
| ) | ||||
| _sym_db.RegisterMessage(ChallengeSolutions) | ||||
| 
 | ||||
| ChallengeSolution = _reflection.GeneratedProtocolMessageType( | ||||
|     "ChallengeSolution", | ||||
|     (_message.Message, ), | ||||
|     { | ||||
|         "DESCRIPTOR": _CHALLENGESOLUTION, | ||||
|         "__module__": "spotify.login5.v3.login5_pb2" | ||||
|         # @@protoc_insertion_point(class_scope:spotify.login5.v3.ChallengeSolution) | ||||
|     }, | ||||
| ) | ||||
| _sym_db.RegisterMessage(ChallengeSolution) | ||||
| 
 | ||||
| LoginRequest = _reflection.GeneratedProtocolMessageType( | ||||
|     "LoginRequest", | ||||
|     (_message.Message, ), | ||||
|     { | ||||
|         "DESCRIPTOR": _LOGINREQUEST, | ||||
|         "__module__": "spotify.login5.v3.login5_pb2" | ||||
|         # @@protoc_insertion_point(class_scope:spotify.login5.v3.LoginRequest) | ||||
|     }, | ||||
| ) | ||||
| _sym_db.RegisterMessage(LoginRequest) | ||||
| 
 | ||||
| LoginOk = _reflection.GeneratedProtocolMessageType( | ||||
|     "LoginOk", | ||||
|     (_message.Message, ), | ||||
|     { | ||||
|         "DESCRIPTOR": _LOGINOK, | ||||
|         "__module__": "spotify.login5.v3.login5_pb2" | ||||
|         # @@protoc_insertion_point(class_scope:spotify.login5.v3.LoginOk) | ||||
|     }, | ||||
| ) | ||||
| _sym_db.RegisterMessage(LoginOk) | ||||
| 
 | ||||
| LoginResponse = _reflection.GeneratedProtocolMessageType( | ||||
|     "LoginResponse", | ||||
|     (_message.Message, ), | ||||
|     { | ||||
|         "DESCRIPTOR": _LOGINRESPONSE, | ||||
|         "__module__": "spotify.login5.v3.login5_pb2" | ||||
|         # @@protoc_insertion_point(class_scope:spotify.login5.v3.LoginResponse) | ||||
|     }, | ||||
| ) | ||||
| _sym_db.RegisterMessage(LoginResponse) | ||||
| 
 | ||||
| DESCRIPTOR._options = None | ||||
| # @@protoc_insertion_point(module_scope) | ||||
							
								
								
									
										263
									
								
								resources/lib/librespot/proto/spotify/login5/v3/UserInfo_pb2.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										263
									
								
								resources/lib/librespot/proto/spotify/login5/v3/UserInfo_pb2.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,263 @@ | |||
| # -*- coding: utf-8 -*- | ||||
| # Generated by the protocol buffer compiler.  DO NOT EDIT! | ||||
| # source: spotify/login5/v3/user_info.proto | ||||
| """Generated protocol buffer code.""" | ||||
| from google.protobuf import descriptor as _descriptor | ||||
| from google.protobuf import message as _message | ||||
| from google.protobuf import reflection as _reflection | ||||
| from google.protobuf import symbol_database as _symbol_database | ||||
| 
 | ||||
| # @@protoc_insertion_point(imports) | ||||
| 
 | ||||
| _sym_db = _symbol_database.Default() | ||||
| 
 | ||||
| DESCRIPTOR = _descriptor.FileDescriptor( | ||||
|     name="spotify/login5/v3/user_info.proto", | ||||
|     package="spotify.login5.v3", | ||||
|     syntax="proto3", | ||||
|     serialized_options=b"\n\024com.spotify.login5v3", | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     serialized_pb= | ||||
|     b'\n!spotify/login5/v3/user_info.proto\x12\x11spotify.login5.v3"\x97\x02\n\x08UserInfo\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\r\n\x05\x65mail\x18\x02 \x01(\t\x12\x16\n\x0e\x65mail_verified\x18\x03 \x01(\x08\x12\x11\n\tbirthdate\x18\x04 \x01(\t\x12\x32\n\x06gender\x18\x05 \x01(\x0e\x32".spotify.login5.v3.UserInfo.Gender\x12\x14\n\x0cphone_number\x18\x06 \x01(\t\x12\x1d\n\x15phone_number_verified\x18\x07 \x01(\x08\x12 \n\x18\x65mail_already_registered\x18\x08 \x01(\x08"8\n\x06Gender\x12\x0b\n\x07UNKNOWN\x10\x00\x12\x08\n\x04MALE\x10\x01\x12\n\n\x06\x46\x45MALE\x10\x02\x12\x0b\n\x07NEUTRAL\x10\x03\x42\x16\n\x14\x63om.spotify.login5v3b\x06proto3', | ||||
| ) | ||||
| 
 | ||||
| _USERINFO_GENDER = _descriptor.EnumDescriptor( | ||||
|     name="Gender", | ||||
|     full_name="spotify.login5.v3.UserInfo.Gender", | ||||
|     filename=None, | ||||
|     file=DESCRIPTOR, | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     values=[ | ||||
|         _descriptor.EnumValueDescriptor( | ||||
|             name="UNKNOWN", | ||||
|             index=0, | ||||
|             number=0, | ||||
|             serialized_options=None, | ||||
|             type=None, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.EnumValueDescriptor( | ||||
|             name="MALE", | ||||
|             index=1, | ||||
|             number=1, | ||||
|             serialized_options=None, | ||||
|             type=None, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.EnumValueDescriptor( | ||||
|             name="FEMALE", | ||||
|             index=2, | ||||
|             number=2, | ||||
|             serialized_options=None, | ||||
|             type=None, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.EnumValueDescriptor( | ||||
|             name="NEUTRAL", | ||||
|             index=3, | ||||
|             number=3, | ||||
|             serialized_options=None, | ||||
|             type=None, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|     ], | ||||
|     containing_type=None, | ||||
|     serialized_options=None, | ||||
|     serialized_start=280, | ||||
|     serialized_end=336, | ||||
| ) | ||||
| _sym_db.RegisterEnumDescriptor(_USERINFO_GENDER) | ||||
| 
 | ||||
| _USERINFO = _descriptor.Descriptor( | ||||
|     name="UserInfo", | ||||
|     full_name="spotify.login5.v3.UserInfo", | ||||
|     filename=None, | ||||
|     file=DESCRIPTOR, | ||||
|     containing_type=None, | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     fields=[ | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="name", | ||||
|             full_name="spotify.login5.v3.UserInfo.name", | ||||
|             index=0, | ||||
|             number=1, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"".decode("utf-8"), | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="email", | ||||
|             full_name="spotify.login5.v3.UserInfo.email", | ||||
|             index=1, | ||||
|             number=2, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"".decode("utf-8"), | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="email_verified", | ||||
|             full_name="spotify.login5.v3.UserInfo.email_verified", | ||||
|             index=2, | ||||
|             number=3, | ||||
|             type=8, | ||||
|             cpp_type=7, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=False, | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="birthdate", | ||||
|             full_name="spotify.login5.v3.UserInfo.birthdate", | ||||
|             index=3, | ||||
|             number=4, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"".decode("utf-8"), | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="gender", | ||||
|             full_name="spotify.login5.v3.UserInfo.gender", | ||||
|             index=4, | ||||
|             number=5, | ||||
|             type=14, | ||||
|             cpp_type=8, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=0, | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="phone_number", | ||||
|             full_name="spotify.login5.v3.UserInfo.phone_number", | ||||
|             index=5, | ||||
|             number=6, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"".decode("utf-8"), | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="phone_number_verified", | ||||
|             full_name="spotify.login5.v3.UserInfo.phone_number_verified", | ||||
|             index=6, | ||||
|             number=7, | ||||
|             type=8, | ||||
|             cpp_type=7, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=False, | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="email_already_registered", | ||||
|             full_name="spotify.login5.v3.UserInfo.email_already_registered", | ||||
|             index=7, | ||||
|             number=8, | ||||
|             type=8, | ||||
|             cpp_type=7, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=False, | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|     ], | ||||
|     extensions=[], | ||||
|     nested_types=[], | ||||
|     enum_types=[ | ||||
|         _USERINFO_GENDER, | ||||
|     ], | ||||
|     serialized_options=None, | ||||
|     is_extendable=False, | ||||
|     syntax="proto3", | ||||
|     extension_ranges=[], | ||||
|     oneofs=[], | ||||
|     serialized_start=57, | ||||
|     serialized_end=336, | ||||
| ) | ||||
| 
 | ||||
| _USERINFO.fields_by_name["gender"].enum_type = _USERINFO_GENDER | ||||
| _USERINFO_GENDER.containing_type = _USERINFO | ||||
| DESCRIPTOR.message_types_by_name["UserInfo"] = _USERINFO | ||||
| _sym_db.RegisterFileDescriptor(DESCRIPTOR) | ||||
| 
 | ||||
| UserInfo = _reflection.GeneratedProtocolMessageType( | ||||
|     "UserInfo", | ||||
|     (_message.Message, ), | ||||
|     { | ||||
|         "DESCRIPTOR": _USERINFO, | ||||
|         "__module__": "spotify.login5.v3.user_info_pb2" | ||||
|         # @@protoc_insertion_point(class_scope:spotify.login5.v3.UserInfo) | ||||
|     }, | ||||
| ) | ||||
| _sym_db.RegisterMessage(UserInfo) | ||||
| 
 | ||||
| DESCRIPTOR._options = None | ||||
| # @@protoc_insertion_point(module_scope) | ||||
|  | @ -0,0 +1,224 @@ | |||
| # -*- coding: utf-8 -*- | ||||
| # Generated by the protocol buffer compiler.  DO NOT EDIT! | ||||
| # source: spotify/login5/v3/challenges/code.proto | ||||
| """Generated protocol buffer code.""" | ||||
| from google.protobuf import descriptor as _descriptor | ||||
| from google.protobuf import message as _message | ||||
| from google.protobuf import reflection as _reflection | ||||
| from google.protobuf import symbol_database as _symbol_database | ||||
| 
 | ||||
| # @@protoc_insertion_point(imports) | ||||
| 
 | ||||
| _sym_db = _symbol_database.Default() | ||||
| 
 | ||||
| DESCRIPTOR = _descriptor.FileDescriptor( | ||||
|     name="spotify/login5/v3/challenges/code.proto", | ||||
|     package="spotify.login5.v3.challenges", | ||||
|     syntax="proto3", | ||||
|     serialized_options=b"\n\024com.spotify.login5v3", | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     serialized_pb= | ||||
|     b'\n\'spotify/login5/v3/challenges/code.proto\x12\x1cspotify.login5.v3.challenges"\xbc\x01\n\rCodeChallenge\x12\x42\n\x06method\x18\x01 \x01(\x0e\x32\x32.spotify.login5.v3.challenges.CodeChallenge.Method\x12\x13\n\x0b\x63ode_length\x18\x02 \x01(\x05\x12\x12\n\nexpires_in\x18\x03 \x01(\x05\x12\x1e\n\x16\x63\x61nonical_phone_number\x18\x04 \x01(\t"\x1e\n\x06Method\x12\x0b\n\x07UNKNOWN\x10\x00\x12\x07\n\x03SMS\x10\x01"\x1c\n\x0c\x43odeSolution\x12\x0c\n\x04\x63ode\x18\x01 \x01(\tB\x16\n\x14\x63om.spotify.login5v3b\x06proto3', | ||||
| ) | ||||
| 
 | ||||
| _CODECHALLENGE_METHOD = _descriptor.EnumDescriptor( | ||||
|     name="Method", | ||||
|     full_name="spotify.login5.v3.challenges.CodeChallenge.Method", | ||||
|     filename=None, | ||||
|     file=DESCRIPTOR, | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     values=[ | ||||
|         _descriptor.EnumValueDescriptor( | ||||
|             name="UNKNOWN", | ||||
|             index=0, | ||||
|             number=0, | ||||
|             serialized_options=None, | ||||
|             type=None, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.EnumValueDescriptor( | ||||
|             name="SMS", | ||||
|             index=1, | ||||
|             number=1, | ||||
|             serialized_options=None, | ||||
|             type=None, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|     ], | ||||
|     containing_type=None, | ||||
|     serialized_options=None, | ||||
|     serialized_start=232, | ||||
|     serialized_end=262, | ||||
| ) | ||||
| _sym_db.RegisterEnumDescriptor(_CODECHALLENGE_METHOD) | ||||
| 
 | ||||
| _CODECHALLENGE = _descriptor.Descriptor( | ||||
|     name="CodeChallenge", | ||||
|     full_name="spotify.login5.v3.challenges.CodeChallenge", | ||||
|     filename=None, | ||||
|     file=DESCRIPTOR, | ||||
|     containing_type=None, | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     fields=[ | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="method", | ||||
|             full_name="spotify.login5.v3.challenges.CodeChallenge.method", | ||||
|             index=0, | ||||
|             number=1, | ||||
|             type=14, | ||||
|             cpp_type=8, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=0, | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="code_length", | ||||
|             full_name="spotify.login5.v3.challenges.CodeChallenge.code_length", | ||||
|             index=1, | ||||
|             number=2, | ||||
|             type=5, | ||||
|             cpp_type=1, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=0, | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="expires_in", | ||||
|             full_name="spotify.login5.v3.challenges.CodeChallenge.expires_in", | ||||
|             index=2, | ||||
|             number=3, | ||||
|             type=5, | ||||
|             cpp_type=1, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=0, | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="canonical_phone_number", | ||||
|             full_name= | ||||
|             "spotify.login5.v3.challenges.CodeChallenge.canonical_phone_number", | ||||
|             index=3, | ||||
|             number=4, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"".decode("utf-8"), | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|     ], | ||||
|     extensions=[], | ||||
|     nested_types=[], | ||||
|     enum_types=[ | ||||
|         _CODECHALLENGE_METHOD, | ||||
|     ], | ||||
|     serialized_options=None, | ||||
|     is_extendable=False, | ||||
|     syntax="proto3", | ||||
|     extension_ranges=[], | ||||
|     oneofs=[], | ||||
|     serialized_start=74, | ||||
|     serialized_end=262, | ||||
| ) | ||||
| 
 | ||||
| _CODESOLUTION = _descriptor.Descriptor( | ||||
|     name="CodeSolution", | ||||
|     full_name="spotify.login5.v3.challenges.CodeSolution", | ||||
|     filename=None, | ||||
|     file=DESCRIPTOR, | ||||
|     containing_type=None, | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     fields=[ | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="code", | ||||
|             full_name="spotify.login5.v3.challenges.CodeSolution.code", | ||||
|             index=0, | ||||
|             number=1, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"".decode("utf-8"), | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|     ], | ||||
|     extensions=[], | ||||
|     nested_types=[], | ||||
|     enum_types=[], | ||||
|     serialized_options=None, | ||||
|     is_extendable=False, | ||||
|     syntax="proto3", | ||||
|     extension_ranges=[], | ||||
|     oneofs=[], | ||||
|     serialized_start=264, | ||||
|     serialized_end=292, | ||||
| ) | ||||
| 
 | ||||
| _CODECHALLENGE.fields_by_name["method"].enum_type = _CODECHALLENGE_METHOD | ||||
| _CODECHALLENGE_METHOD.containing_type = _CODECHALLENGE | ||||
| DESCRIPTOR.message_types_by_name["CodeChallenge"] = _CODECHALLENGE | ||||
| DESCRIPTOR.message_types_by_name["CodeSolution"] = _CODESOLUTION | ||||
| _sym_db.RegisterFileDescriptor(DESCRIPTOR) | ||||
| 
 | ||||
| CodeChallenge = _reflection.GeneratedProtocolMessageType( | ||||
|     "CodeChallenge", | ||||
|     (_message.Message, ), | ||||
|     { | ||||
|         "DESCRIPTOR": _CODECHALLENGE, | ||||
|         "__module__": "spotify.login5.v3.challenges.code_pb2" | ||||
|         # @@protoc_insertion_point(class_scope:spotify.login5.v3.challenges.CodeChallenge) | ||||
|     }, | ||||
| ) | ||||
| _sym_db.RegisterMessage(CodeChallenge) | ||||
| 
 | ||||
| CodeSolution = _reflection.GeneratedProtocolMessageType( | ||||
|     "CodeSolution", | ||||
|     (_message.Message, ), | ||||
|     { | ||||
|         "DESCRIPTOR": _CODESOLUTION, | ||||
|         "__module__": "spotify.login5.v3.challenges.code_pb2" | ||||
|         # @@protoc_insertion_point(class_scope:spotify.login5.v3.challenges.CodeSolution) | ||||
|     }, | ||||
| ) | ||||
| _sym_db.RegisterMessage(CodeSolution) | ||||
| 
 | ||||
| DESCRIPTOR._options = None | ||||
| # @@protoc_insertion_point(module_scope) | ||||
|  | @ -0,0 +1,176 @@ | |||
| # -*- coding: utf-8 -*- | ||||
| # Generated by the protocol buffer compiler.  DO NOT EDIT! | ||||
| # source: spotify/login5/v3/challenges/hashcash.proto | ||||
| """Generated protocol buffer code.""" | ||||
| from google.protobuf import descriptor as _descriptor | ||||
| from google.protobuf import \ | ||||
|     duration_pb2 as google_dot_protobuf_dot_duration__pb2 | ||||
| from google.protobuf import message as _message | ||||
| from google.protobuf import reflection as _reflection | ||||
| from google.protobuf import symbol_database as _symbol_database | ||||
| 
 | ||||
| # @@protoc_insertion_point(imports) | ||||
| 
 | ||||
| _sym_db = _symbol_database.Default() | ||||
| 
 | ||||
| DESCRIPTOR = _descriptor.FileDescriptor( | ||||
|     name="spotify/login5/v3/challenges/hashcash.proto", | ||||
|     package="spotify.login5.v3.challenges", | ||||
|     syntax="proto3", | ||||
|     serialized_options=b"\n\024com.spotify.login5v3", | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     serialized_pb= | ||||
|     b'\n+spotify/login5/v3/challenges/hashcash.proto\x12\x1cspotify.login5.v3.challenges\x1a\x1egoogle/protobuf/duration.proto"3\n\x11HashcashChallenge\x12\x0e\n\x06prefix\x18\x01 \x01(\x0c\x12\x0e\n\x06length\x18\x02 \x01(\x05"O\n\x10HashcashSolution\x12\x0e\n\x06suffix\x18\x01 \x01(\x0c\x12+\n\x08\x64uration\x18\x02 \x01(\x0b\x32\x19.google.protobuf.DurationB\x16\n\x14\x63om.spotify.login5v3b\x06proto3', | ||||
|     dependencies=[ | ||||
|         google_dot_protobuf_dot_duration__pb2.DESCRIPTOR, | ||||
|     ], | ||||
| ) | ||||
| 
 | ||||
| _HASHCASHCHALLENGE = _descriptor.Descriptor( | ||||
|     name="HashcashChallenge", | ||||
|     full_name="spotify.login5.v3.challenges.HashcashChallenge", | ||||
|     filename=None, | ||||
|     file=DESCRIPTOR, | ||||
|     containing_type=None, | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     fields=[ | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="prefix", | ||||
|             full_name="spotify.login5.v3.challenges.HashcashChallenge.prefix", | ||||
|             index=0, | ||||
|             number=1, | ||||
|             type=12, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"", | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="length", | ||||
|             full_name="spotify.login5.v3.challenges.HashcashChallenge.length", | ||||
|             index=1, | ||||
|             number=2, | ||||
|             type=5, | ||||
|             cpp_type=1, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=0, | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|     ], | ||||
|     extensions=[], | ||||
|     nested_types=[], | ||||
|     enum_types=[], | ||||
|     serialized_options=None, | ||||
|     is_extendable=False, | ||||
|     syntax="proto3", | ||||
|     extension_ranges=[], | ||||
|     oneofs=[], | ||||
|     serialized_start=109, | ||||
|     serialized_end=160, | ||||
| ) | ||||
| 
 | ||||
| _HASHCASHSOLUTION = _descriptor.Descriptor( | ||||
|     name="HashcashSolution", | ||||
|     full_name="spotify.login5.v3.challenges.HashcashSolution", | ||||
|     filename=None, | ||||
|     file=DESCRIPTOR, | ||||
|     containing_type=None, | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     fields=[ | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="suffix", | ||||
|             full_name="spotify.login5.v3.challenges.HashcashSolution.suffix", | ||||
|             index=0, | ||||
|             number=1, | ||||
|             type=12, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"", | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="duration", | ||||
|             full_name="spotify.login5.v3.challenges.HashcashSolution.duration", | ||||
|             index=1, | ||||
|             number=2, | ||||
|             type=11, | ||||
|             cpp_type=10, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=None, | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|     ], | ||||
|     extensions=[], | ||||
|     nested_types=[], | ||||
|     enum_types=[], | ||||
|     serialized_options=None, | ||||
|     is_extendable=False, | ||||
|     syntax="proto3", | ||||
|     extension_ranges=[], | ||||
|     oneofs=[], | ||||
|     serialized_start=162, | ||||
|     serialized_end=241, | ||||
| ) | ||||
| 
 | ||||
| _HASHCASHSOLUTION.fields_by_name[ | ||||
|     "duration"].message_type = google_dot_protobuf_dot_duration__pb2._DURATION | ||||
| DESCRIPTOR.message_types_by_name["HashcashChallenge"] = _HASHCASHCHALLENGE | ||||
| DESCRIPTOR.message_types_by_name["HashcashSolution"] = _HASHCASHSOLUTION | ||||
| _sym_db.RegisterFileDescriptor(DESCRIPTOR) | ||||
| 
 | ||||
| HashcashChallenge = _reflection.GeneratedProtocolMessageType( | ||||
|     "HashcashChallenge", | ||||
|     (_message.Message, ), | ||||
|     { | ||||
|         "DESCRIPTOR": _HASHCASHCHALLENGE, | ||||
|         "__module__": "spotify.login5.v3.challenges.hashcash_pb2" | ||||
|         # @@protoc_insertion_point(class_scope:spotify.login5.v3.challenges.HashcashChallenge) | ||||
|     }, | ||||
| ) | ||||
| _sym_db.RegisterMessage(HashcashChallenge) | ||||
| 
 | ||||
| HashcashSolution = _reflection.GeneratedProtocolMessageType( | ||||
|     "HashcashSolution", | ||||
|     (_message.Message, ), | ||||
|     { | ||||
|         "DESCRIPTOR": _HASHCASHSOLUTION, | ||||
|         "__module__": "spotify.login5.v3.challenges.hashcash_pb2" | ||||
|         # @@protoc_insertion_point(class_scope:spotify.login5.v3.challenges.HashcashSolution) | ||||
|     }, | ||||
| ) | ||||
| _sym_db.RegisterMessage(HashcashSolution) | ||||
| 
 | ||||
| DESCRIPTOR._options = None | ||||
| # @@protoc_insertion_point(module_scope) | ||||
|  | @ -0,0 +1,483 @@ | |||
| # -*- coding: utf-8 -*- | ||||
| # Generated by the protocol buffer compiler.  DO NOT EDIT! | ||||
| # source: spotify/login5/v3/credentials/credentials.proto | ||||
| """Generated protocol buffer code.""" | ||||
| from google.protobuf import descriptor as _descriptor | ||||
| from google.protobuf import message as _message | ||||
| from google.protobuf import reflection as _reflection | ||||
| from google.protobuf import symbol_database as _symbol_database | ||||
| 
 | ||||
| # @@protoc_insertion_point(imports) | ||||
| 
 | ||||
| _sym_db = _symbol_database.Default() | ||||
| 
 | ||||
| DESCRIPTOR = _descriptor.FileDescriptor( | ||||
|     name="spotify/login5/v3/credentials/credentials.proto", | ||||
|     package="spotify.login5.v3.credentials", | ||||
|     syntax="proto3", | ||||
|     serialized_options=b"\n\024com.spotify.login5v3", | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     serialized_pb= | ||||
|     b'\n/spotify/login5/v3/credentials/credentials.proto\x12\x1dspotify.login5.v3.credentials"2\n\x10StoredCredential\x12\x10\n\x08username\x18\x01 \x01(\t\x12\x0c\n\x04\x64\x61ta\x18\x02 \x01(\x0c"9\n\x08Password\x12\n\n\x02id\x18\x01 \x01(\t\x12\x10\n\x08password\x18\x02 \x01(\t\x12\x0f\n\x07padding\x18\x03 \x01(\x0c";\n\x13\x46\x61\x63\x65\x62ookAccessToken\x12\x0e\n\x06\x66\x62_uid\x18\x01 \x01(\t\x12\x14\n\x0c\x61\x63\x63\x65ss_token\x18\x02 \x01(\t"\x1d\n\x0cOneTimeToken\x12\r\n\x05token\x18\x01 \x01(\t"|\n\x15ParentChildCredential\x12\x10\n\x08\x63hild_id\x18\x01 \x01(\t\x12Q\n\x18parent_stored_credential\x18\x02 \x01(\x0b\x32/.spotify.login5.v3.credentials.StoredCredential"S\n\x15\x41ppleSignInCredential\x12\x11\n\tauth_code\x18\x01 \x01(\t\x12\x14\n\x0credirect_uri\x18\x02 \x01(\t\x12\x11\n\tbundle_id\x18\x03 \x01(\tB\x16\n\x14\x63om.spotify.login5v3b\x06proto3', | ||||
| ) | ||||
| 
 | ||||
| _STOREDCREDENTIAL = _descriptor.Descriptor( | ||||
|     name="StoredCredential", | ||||
|     full_name="spotify.login5.v3.credentials.StoredCredential", | ||||
|     filename=None, | ||||
|     file=DESCRIPTOR, | ||||
|     containing_type=None, | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     fields=[ | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="username", | ||||
|             full_name="spotify.login5.v3.credentials.StoredCredential.username", | ||||
|             index=0, | ||||
|             number=1, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"".decode("utf-8"), | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="data", | ||||
|             full_name="spotify.login5.v3.credentials.StoredCredential.data", | ||||
|             index=1, | ||||
|             number=2, | ||||
|             type=12, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"", | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|     ], | ||||
|     extensions=[], | ||||
|     nested_types=[], | ||||
|     enum_types=[], | ||||
|     serialized_options=None, | ||||
|     is_extendable=False, | ||||
|     syntax="proto3", | ||||
|     extension_ranges=[], | ||||
|     oneofs=[], | ||||
|     serialized_start=82, | ||||
|     serialized_end=132, | ||||
| ) | ||||
| 
 | ||||
| _PASSWORD = _descriptor.Descriptor( | ||||
|     name="Password", | ||||
|     full_name="spotify.login5.v3.credentials.Password", | ||||
|     filename=None, | ||||
|     file=DESCRIPTOR, | ||||
|     containing_type=None, | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     fields=[ | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="id", | ||||
|             full_name="spotify.login5.v3.credentials.Password.id", | ||||
|             index=0, | ||||
|             number=1, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"".decode("utf-8"), | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="password", | ||||
|             full_name="spotify.login5.v3.credentials.Password.password", | ||||
|             index=1, | ||||
|             number=2, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"".decode("utf-8"), | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="padding", | ||||
|             full_name="spotify.login5.v3.credentials.Password.padding", | ||||
|             index=2, | ||||
|             number=3, | ||||
|             type=12, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"", | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|     ], | ||||
|     extensions=[], | ||||
|     nested_types=[], | ||||
|     enum_types=[], | ||||
|     serialized_options=None, | ||||
|     is_extendable=False, | ||||
|     syntax="proto3", | ||||
|     extension_ranges=[], | ||||
|     oneofs=[], | ||||
|     serialized_start=134, | ||||
|     serialized_end=191, | ||||
| ) | ||||
| 
 | ||||
| _FACEBOOKACCESSTOKEN = _descriptor.Descriptor( | ||||
|     name="FacebookAccessToken", | ||||
|     full_name="spotify.login5.v3.credentials.FacebookAccessToken", | ||||
|     filename=None, | ||||
|     file=DESCRIPTOR, | ||||
|     containing_type=None, | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     fields=[ | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="fb_uid", | ||||
|             full_name= | ||||
|             "spotify.login5.v3.credentials.FacebookAccessToken.fb_uid", | ||||
|             index=0, | ||||
|             number=1, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"".decode("utf-8"), | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="access_token", | ||||
|             full_name= | ||||
|             "spotify.login5.v3.credentials.FacebookAccessToken.access_token", | ||||
|             index=1, | ||||
|             number=2, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"".decode("utf-8"), | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|     ], | ||||
|     extensions=[], | ||||
|     nested_types=[], | ||||
|     enum_types=[], | ||||
|     serialized_options=None, | ||||
|     is_extendable=False, | ||||
|     syntax="proto3", | ||||
|     extension_ranges=[], | ||||
|     oneofs=[], | ||||
|     serialized_start=193, | ||||
|     serialized_end=252, | ||||
| ) | ||||
| 
 | ||||
| _ONETIMETOKEN = _descriptor.Descriptor( | ||||
|     name="OneTimeToken", | ||||
|     full_name="spotify.login5.v3.credentials.OneTimeToken", | ||||
|     filename=None, | ||||
|     file=DESCRIPTOR, | ||||
|     containing_type=None, | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     fields=[ | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="token", | ||||
|             full_name="spotify.login5.v3.credentials.OneTimeToken.token", | ||||
|             index=0, | ||||
|             number=1, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"".decode("utf-8"), | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|     ], | ||||
|     extensions=[], | ||||
|     nested_types=[], | ||||
|     enum_types=[], | ||||
|     serialized_options=None, | ||||
|     is_extendable=False, | ||||
|     syntax="proto3", | ||||
|     extension_ranges=[], | ||||
|     oneofs=[], | ||||
|     serialized_start=254, | ||||
|     serialized_end=283, | ||||
| ) | ||||
| 
 | ||||
| _PARENTCHILDCREDENTIAL = _descriptor.Descriptor( | ||||
|     name="ParentChildCredential", | ||||
|     full_name="spotify.login5.v3.credentials.ParentChildCredential", | ||||
|     filename=None, | ||||
|     file=DESCRIPTOR, | ||||
|     containing_type=None, | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     fields=[ | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="child_id", | ||||
|             full_name= | ||||
|             "spotify.login5.v3.credentials.ParentChildCredential.child_id", | ||||
|             index=0, | ||||
|             number=1, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"".decode("utf-8"), | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="parent_stored_credential", | ||||
|             full_name= | ||||
|             "spotify.login5.v3.credentials.ParentChildCredential.parent_stored_credential", | ||||
|             index=1, | ||||
|             number=2, | ||||
|             type=11, | ||||
|             cpp_type=10, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=None, | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|     ], | ||||
|     extensions=[], | ||||
|     nested_types=[], | ||||
|     enum_types=[], | ||||
|     serialized_options=None, | ||||
|     is_extendable=False, | ||||
|     syntax="proto3", | ||||
|     extension_ranges=[], | ||||
|     oneofs=[], | ||||
|     serialized_start=285, | ||||
|     serialized_end=409, | ||||
| ) | ||||
| 
 | ||||
| _APPLESIGNINCREDENTIAL = _descriptor.Descriptor( | ||||
|     name="AppleSignInCredential", | ||||
|     full_name="spotify.login5.v3.credentials.AppleSignInCredential", | ||||
|     filename=None, | ||||
|     file=DESCRIPTOR, | ||||
|     containing_type=None, | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     fields=[ | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="auth_code", | ||||
|             full_name= | ||||
|             "spotify.login5.v3.credentials.AppleSignInCredential.auth_code", | ||||
|             index=0, | ||||
|             number=1, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"".decode("utf-8"), | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="redirect_uri", | ||||
|             full_name= | ||||
|             "spotify.login5.v3.credentials.AppleSignInCredential.redirect_uri", | ||||
|             index=1, | ||||
|             number=2, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"".decode("utf-8"), | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="bundle_id", | ||||
|             full_name= | ||||
|             "spotify.login5.v3.credentials.AppleSignInCredential.bundle_id", | ||||
|             index=2, | ||||
|             number=3, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"".decode("utf-8"), | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|     ], | ||||
|     extensions=[], | ||||
|     nested_types=[], | ||||
|     enum_types=[], | ||||
|     serialized_options=None, | ||||
|     is_extendable=False, | ||||
|     syntax="proto3", | ||||
|     extension_ranges=[], | ||||
|     oneofs=[], | ||||
|     serialized_start=411, | ||||
|     serialized_end=494, | ||||
| ) | ||||
| 
 | ||||
| _PARENTCHILDCREDENTIAL.fields_by_name[ | ||||
|     "parent_stored_credential"].message_type = _STOREDCREDENTIAL | ||||
| DESCRIPTOR.message_types_by_name["StoredCredential"] = _STOREDCREDENTIAL | ||||
| DESCRIPTOR.message_types_by_name["Password"] = _PASSWORD | ||||
| DESCRIPTOR.message_types_by_name["FacebookAccessToken"] = _FACEBOOKACCESSTOKEN | ||||
| DESCRIPTOR.message_types_by_name["OneTimeToken"] = _ONETIMETOKEN | ||||
| DESCRIPTOR.message_types_by_name[ | ||||
|     "ParentChildCredential"] = _PARENTCHILDCREDENTIAL | ||||
| DESCRIPTOR.message_types_by_name[ | ||||
|     "AppleSignInCredential"] = _APPLESIGNINCREDENTIAL | ||||
| _sym_db.RegisterFileDescriptor(DESCRIPTOR) | ||||
| 
 | ||||
| StoredCredential = _reflection.GeneratedProtocolMessageType( | ||||
|     "StoredCredential", | ||||
|     (_message.Message, ), | ||||
|     { | ||||
|         "DESCRIPTOR": _STOREDCREDENTIAL, | ||||
|         "__module__": "spotify.login5.v3.credentials.credentials_pb2" | ||||
|         # @@protoc_insertion_point(class_scope:spotify.login5.v3.credentials.StoredCredential) | ||||
|     }, | ||||
| ) | ||||
| _sym_db.RegisterMessage(StoredCredential) | ||||
| 
 | ||||
| Password = _reflection.GeneratedProtocolMessageType( | ||||
|     "Password", | ||||
|     (_message.Message, ), | ||||
|     { | ||||
|         "DESCRIPTOR": _PASSWORD, | ||||
|         "__module__": "spotify.login5.v3.credentials.credentials_pb2" | ||||
|         # @@protoc_insertion_point(class_scope:spotify.login5.v3.credentials.Password) | ||||
|     }, | ||||
| ) | ||||
| _sym_db.RegisterMessage(Password) | ||||
| 
 | ||||
| FacebookAccessToken = _reflection.GeneratedProtocolMessageType( | ||||
|     "FacebookAccessToken", | ||||
|     (_message.Message, ), | ||||
|     { | ||||
|         "DESCRIPTOR": _FACEBOOKACCESSTOKEN, | ||||
|         "__module__": "spotify.login5.v3.credentials.credentials_pb2" | ||||
|         # @@protoc_insertion_point(class_scope:spotify.login5.v3.credentials.FacebookAccessToken) | ||||
|     }, | ||||
| ) | ||||
| _sym_db.RegisterMessage(FacebookAccessToken) | ||||
| 
 | ||||
| OneTimeToken = _reflection.GeneratedProtocolMessageType( | ||||
|     "OneTimeToken", | ||||
|     (_message.Message, ), | ||||
|     { | ||||
|         "DESCRIPTOR": _ONETIMETOKEN, | ||||
|         "__module__": "spotify.login5.v3.credentials.credentials_pb2" | ||||
|         # @@protoc_insertion_point(class_scope:spotify.login5.v3.credentials.OneTimeToken) | ||||
|     }, | ||||
| ) | ||||
| _sym_db.RegisterMessage(OneTimeToken) | ||||
| 
 | ||||
| ParentChildCredential = _reflection.GeneratedProtocolMessageType( | ||||
|     "ParentChildCredential", | ||||
|     (_message.Message, ), | ||||
|     { | ||||
|         "DESCRIPTOR": _PARENTCHILDCREDENTIAL, | ||||
|         "__module__": "spotify.login5.v3.credentials.credentials_pb2" | ||||
|         # @@protoc_insertion_point(class_scope:spotify.login5.v3.credentials.ParentChildCredential) | ||||
|     }, | ||||
| ) | ||||
| _sym_db.RegisterMessage(ParentChildCredential) | ||||
| 
 | ||||
| AppleSignInCredential = _reflection.GeneratedProtocolMessageType( | ||||
|     "AppleSignInCredential", | ||||
|     (_message.Message, ), | ||||
|     { | ||||
|         "DESCRIPTOR": _APPLESIGNINCREDENTIAL, | ||||
|         "__module__": "spotify.login5.v3.credentials.credentials_pb2" | ||||
|         # @@protoc_insertion_point(class_scope:spotify.login5.v3.credentials.AppleSignInCredential) | ||||
|     }, | ||||
| ) | ||||
| _sym_db.RegisterMessage(AppleSignInCredential) | ||||
| 
 | ||||
| DESCRIPTOR._options = None | ||||
| # @@protoc_insertion_point(module_scope) | ||||
|  | @ -0,0 +1,119 @@ | |||
| # -*- coding: utf-8 -*- | ||||
| # Generated by the protocol buffer compiler.  DO NOT EDIT! | ||||
| # source: spotify/login5/v3/identifiers/identifiers.proto | ||||
| """Generated protocol buffer code.""" | ||||
| from google.protobuf import descriptor as _descriptor | ||||
| from google.protobuf import message as _message | ||||
| from google.protobuf import reflection as _reflection | ||||
| from google.protobuf import symbol_database as _symbol_database | ||||
| 
 | ||||
| # @@protoc_insertion_point(imports) | ||||
| 
 | ||||
| _sym_db = _symbol_database.Default() | ||||
| 
 | ||||
| DESCRIPTOR = _descriptor.FileDescriptor( | ||||
|     name="spotify/login5/v3/identifiers/identifiers.proto", | ||||
|     package="spotify.login5.v3.identifiers", | ||||
|     syntax="proto3", | ||||
|     serialized_options=b"\n\024com.spotify.login5v3", | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     serialized_pb= | ||||
|     b'\n/spotify/login5/v3/identifiers/identifiers.proto\x12\x1dspotify.login5.v3.identifiers"U\n\x0bPhoneNumber\x12\x0e\n\x06number\x18\x01 \x01(\t\x12\x18\n\x10iso_country_code\x18\x02 \x01(\t\x12\x1c\n\x14\x63ountry_calling_code\x18\x03 \x01(\tB\x16\n\x14\x63om.spotify.login5v3b\x06proto3', | ||||
| ) | ||||
| 
 | ||||
| _PHONENUMBER = _descriptor.Descriptor( | ||||
|     name="PhoneNumber", | ||||
|     full_name="spotify.login5.v3.identifiers.PhoneNumber", | ||||
|     filename=None, | ||||
|     file=DESCRIPTOR, | ||||
|     containing_type=None, | ||||
|     create_key=_descriptor._internal_create_key, | ||||
|     fields=[ | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="number", | ||||
|             full_name="spotify.login5.v3.identifiers.PhoneNumber.number", | ||||
|             index=0, | ||||
|             number=1, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"".decode("utf-8"), | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="iso_country_code", | ||||
|             full_name= | ||||
|             "spotify.login5.v3.identifiers.PhoneNumber.iso_country_code", | ||||
|             index=1, | ||||
|             number=2, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"".decode("utf-8"), | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|         _descriptor.FieldDescriptor( | ||||
|             name="country_calling_code", | ||||
|             full_name= | ||||
|             "spotify.login5.v3.identifiers.PhoneNumber.country_calling_code", | ||||
|             index=2, | ||||
|             number=3, | ||||
|             type=9, | ||||
|             cpp_type=9, | ||||
|             label=1, | ||||
|             has_default_value=False, | ||||
|             default_value=b"".decode("utf-8"), | ||||
|             message_type=None, | ||||
|             enum_type=None, | ||||
|             containing_type=None, | ||||
|             is_extension=False, | ||||
|             extension_scope=None, | ||||
|             serialized_options=None, | ||||
|             file=DESCRIPTOR, | ||||
|             create_key=_descriptor._internal_create_key, | ||||
|         ), | ||||
|     ], | ||||
|     extensions=[], | ||||
|     nested_types=[], | ||||
|     enum_types=[], | ||||
|     serialized_options=None, | ||||
|     is_extendable=False, | ||||
|     syntax="proto3", | ||||
|     extension_ranges=[], | ||||
|     oneofs=[], | ||||
|     serialized_start=82, | ||||
|     serialized_end=167, | ||||
| ) | ||||
| 
 | ||||
| DESCRIPTOR.message_types_by_name["PhoneNumber"] = _PHONENUMBER | ||||
| _sym_db.RegisterFileDescriptor(DESCRIPTOR) | ||||
| 
 | ||||
| PhoneNumber = _reflection.GeneratedProtocolMessageType( | ||||
|     "PhoneNumber", | ||||
|     (_message.Message, ), | ||||
|     { | ||||
|         "DESCRIPTOR": _PHONENUMBER, | ||||
|         "__module__": "spotify.login5.v3.identifiers.identifiers_pb2" | ||||
|         # @@protoc_insertion_point(class_scope:spotify.login5.v3.identifiers.PhoneNumber) | ||||
|     }, | ||||
| ) | ||||
| _sym_db.RegisterMessage(PhoneNumber) | ||||
| 
 | ||||
| DESCRIPTOR._options = None | ||||
| # @@protoc_insertion_point(module_scope) | ||||
							
								
								
									
										103
									
								
								resources/lib/librespot/structure.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								resources/lib/librespot/structure.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,103 @@ | |||
| from __future__ import annotations | ||||
| import typing | ||||
| 
 | ||||
| if typing.TYPE_CHECKING: | ||||
|     from librespot.audio import AbsChunkedInputStream | ||||
|     from librespot.audio.format import SuperAudioFormat | ||||
|     from librespot.core import DealerClient, Session | ||||
|     from librespot.crypto import Packet | ||||
|     from librespot.mercury import MercuryClient | ||||
|     from librespot.proto import Metadata_pb2 as Metadata | ||||
| 
 | ||||
| 
 | ||||
| class AudioDecrypt: | ||||
|     def decrypt_chunk(self, chunk_index: int, buffer: bytes): | ||||
|         raise NotImplementedError | ||||
| 
 | ||||
|     def decrypt_time_ms(self): | ||||
|         raise NotImplementedError | ||||
| 
 | ||||
| 
 | ||||
| class AudioQualityPicker: | ||||
|     def get_file(self, | ||||
|                  files: typing.List[Metadata.AudioFile]) -> Metadata.AudioFile: | ||||
|         raise NotImplementedError | ||||
| 
 | ||||
| 
 | ||||
| class Closeable: | ||||
|     def close(self) -> None: | ||||
|         raise NotImplementedError | ||||
| 
 | ||||
| 
 | ||||
| class FeederException(Exception): | ||||
|     pass | ||||
| 
 | ||||
| 
 | ||||
| class GeneralAudioStream: | ||||
|     def stream(self) -> AbsChunkedInputStream: | ||||
|         raise NotImplementedError | ||||
| 
 | ||||
|     def codec(self) -> SuperAudioFormat: | ||||
|         raise NotImplementedError | ||||
| 
 | ||||
|     def describe(self) -> str: | ||||
|         raise NotImplementedError | ||||
| 
 | ||||
|     def decrypt_time_ms(self) -> int: | ||||
|         raise NotImplementedError | ||||
| 
 | ||||
| 
 | ||||
| class GeneralWritableStream: | ||||
|     def write_chunk(self, buffer: bytearray, chunk_index: int, cached: bool): | ||||
|         raise NotImplementedError | ||||
| 
 | ||||
| 
 | ||||
| class HaltListener: | ||||
|     def stream_read_halted(self, chunk: int, _time: int) -> None: | ||||
|         raise NotImplementedError | ||||
| 
 | ||||
|     def stream_read_resumed(self, chunk: int, _time: int) -> None: | ||||
|         raise NotImplementedError | ||||
| 
 | ||||
| 
 | ||||
| class MessageListener: | ||||
|     def on_message(self, uri: str, headers: typing.Dict[str, str], | ||||
|                    payload: bytes): | ||||
|         raise NotImplementedError | ||||
| 
 | ||||
| 
 | ||||
| class NoopAudioDecrypt(AudioDecrypt): | ||||
|     def decrypt_chunk(self, chunk_index: int, buffer: bytes): | ||||
|         return buffer | ||||
| 
 | ||||
|     def decrypt_time_ms(self): | ||||
|         return 0 | ||||
| 
 | ||||
| 
 | ||||
| class PacketsReceiver: | ||||
|     def dispatch(self, packet: Packet): | ||||
|         raise NotImplementedError | ||||
| 
 | ||||
| 
 | ||||
| class RequestListener: | ||||
|     def on_request(self, mid: str, pid: int, sender: str, | ||||
|                    command: typing.Any) -> DealerClient.RequestResult: | ||||
|         raise NotImplementedError | ||||
| 
 | ||||
| 
 | ||||
| class Runnable: | ||||
|     def run(self): | ||||
|         raise NotImplementedError | ||||
| 
 | ||||
| 
 | ||||
| class SessionListener: | ||||
|     def session_closing(self, session: Session) -> None: | ||||
|         raise NotImplementedError | ||||
| 
 | ||||
|     def session_changed(self, session: Session) -> None: | ||||
|         raise NotImplementedError | ||||
| 
 | ||||
| 
 | ||||
| class SubListener: | ||||
|     def event(self, resp: MercuryClient.Response) -> None: | ||||
|         raise NotImplementedError | ||||
							
								
								
									
										117
									
								
								resources/lib/librespot/util.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										117
									
								
								resources/lib/librespot/util.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,117 @@ | |||
| from Cryptodome import Random | ||||
| import binascii | ||||
| import math | ||||
| 
 | ||||
| 
 | ||||
| def bytes_to_hex(buffer: bytes) -> str: | ||||
|     """ | ||||
|     Convert bytes to hex | ||||
|     Args: | ||||
|         buffer: Bytes to convert | ||||
|     Returns: | ||||
|         hex | ||||
|     """ | ||||
|     return binascii.hexlify(buffer).decode() | ||||
| 
 | ||||
| 
 | ||||
| def hex_to_bytes(s: str) -> bytes: | ||||
|     return binascii.unhexlify(s) | ||||
| 
 | ||||
| 
 | ||||
| def int_to_bytes(i: int): | ||||
|     """ | ||||
|     Convert an integer to a byte(s) | ||||
|     Args: | ||||
|         i: Integer to convert | ||||
|     Returns: | ||||
|         bytes | ||||
|     """ | ||||
|     width = i.bit_length() | ||||
|     width += 8 - ((width % 8) or 8) | ||||
|     fmt = '%%0%dx' % (width // 4) | ||||
|     return b"\x00" if i == 0 else binascii.unhexlify(fmt % i) | ||||
| 
 | ||||
| 
 | ||||
| def random_hex_string(length: int): | ||||
|     buffer = Random.get_random_bytes(int(length / 2)) | ||||
|     return bytes_to_hex(buffer) | ||||
| 
 | ||||
| 
 | ||||
| class Base62: | ||||
|     standard_base = 256 | ||||
|     target_base = 62 | ||||
|     alphabet: bytes | ||||
|     lookup: bytearray | ||||
| 
 | ||||
|     def __init__(self, alphabet: bytes): | ||||
|         self.alphabet = alphabet | ||||
|         self.create_lookup_table() | ||||
| 
 | ||||
|     @staticmethod | ||||
|     def create_instance_with_inverted_character_set(): | ||||
|         return Base62(Base62.CharacterSets.inverted) | ||||
| 
 | ||||
|     def encode(self, message: bytes, length: int = -1): | ||||
|         indices = self.convert(message, self.standard_base, self.target_base, | ||||
|                                length) | ||||
|         return self.translate(indices, self.alphabet) | ||||
| 
 | ||||
|     def decode(self, encoded: bytes, length: int = -1): | ||||
|         prepared = self.translate(encoded, self.lookup) | ||||
|         return self.convert(prepared, self.target_base, self.standard_base, | ||||
|                             length) | ||||
| 
 | ||||
|     def translate(self, indices: bytes, dictionary: bytes): | ||||
|         translation = bytearray(len(indices)) | ||||
|         for i in range(len(indices)): | ||||
|             translation[i] = dictionary[int.from_bytes(bytes([indices[i]]), "big")] | ||||
|         return translation | ||||
| 
 | ||||
|     def convert(self, message: bytes, source_base: int, target_base: int, | ||||
|                 length: int): | ||||
|         estimated_length = self.estimate_output_length( | ||||
|             len(message), source_base, target_base) if length == -1 else length | ||||
|         out = b"" | ||||
|         source = message | ||||
|         while len(source) > 0: | ||||
|             quotient = b"" | ||||
|             remainder = 0 | ||||
|             for b in source: | ||||
|                 accumulator = int(b & 0xff) + remainder * source_base | ||||
|                 digit = int( | ||||
|                     (accumulator - (accumulator % target_base)) / target_base) | ||||
|                 remainder = int(accumulator % target_base) | ||||
|                 if len(quotient) > 0 or digit > 0: | ||||
|                     quotient += bytes([digit]) | ||||
|             out += bytes([remainder]) | ||||
|             source = quotient | ||||
|         if len(out) < estimated_length: | ||||
|             size = len(out) | ||||
|             for _ in range(estimated_length - size): | ||||
|                 out += bytes([0]) | ||||
|             return self.reverse(out) | ||||
|         if len(out) > estimated_length: | ||||
|             return self.reverse(out[:estimated_length]) | ||||
|         return self.reverse(out) | ||||
| 
 | ||||
|     def estimate_output_length(self, input_length: int, source_base: int, | ||||
|                                target_base: int): | ||||
|         return int( | ||||
|             math.ceil((math.log(source_base) / math.log(target_base)) * | ||||
|                       input_length)) | ||||
| 
 | ||||
|     def reverse(self, arr: bytes): | ||||
|         length = len(arr) | ||||
|         reversed_arr = bytearray(length) | ||||
|         for i in range(length): | ||||
|             reversed_arr[length - i - 1] = arr[i] | ||||
|         return bytes(reversed_arr) | ||||
| 
 | ||||
|     def create_lookup_table(self): | ||||
|         self.lookup = bytearray(256) | ||||
|         for i in range(len(self.alphabet)): | ||||
|             self.lookup[self.alphabet[i]] = i & 0xff | ||||
| 
 | ||||
|     class CharacterSets: | ||||
|         gmp = b'0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz' | ||||
|         inverted = b'0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' | ||||
							
								
								
									
										345
									
								
								resources/lib/librespot/zeroconf.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										345
									
								
								resources/lib/librespot/zeroconf.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,345 @@ | |||
| from __future__ import annotations | ||||
| from Cryptodome.Cipher import AES | ||||
| from Cryptodome.Hash import HMAC, SHA1 | ||||
| from Cryptodome.Util import Counter | ||||
| from librespot import util, Version | ||||
| from librespot.core import Session | ||||
| from librespot.crypto import DiffieHellman | ||||
| from librespot.proto import Connect_pb2 as Connect | ||||
| from librespot.structure import Closeable, Runnable, SessionListener | ||||
| import base64 | ||||
| import concurrent.futures | ||||
| import copy | ||||
| import io | ||||
| import json | ||||
| import logging | ||||
| import random | ||||
| import socket | ||||
| import threading | ||||
| import typing | ||||
| import urllib.parse | ||||
| import zeroconf | ||||
| 
 | ||||
| 
 | ||||
| class ZeroconfServer(Closeable): | ||||
|     logger = logging.getLogger("Librespot:ZeroconfServer") | ||||
|     service = "_spotify-connect._tcp.local." | ||||
|     __connecting_username: typing.Union[str, None] = None | ||||
|     __connection_lock = threading.Condition() | ||||
|     __default_get_info_fields = { | ||||
|         "status": 101, | ||||
|         "statusString": "OK", | ||||
|         "spotifyError": 0, | ||||
|         "version": "2.7.1", | ||||
|         "libraryVersion": Version.version_name, | ||||
|         "accountReq": "PREMIUM", | ||||
|         "brandDisplayName": "kokarare1212", | ||||
|         "modelDisplayName": "librespot-python", | ||||
|         "voiceSupport": "NO", | ||||
|         "availability": "", | ||||
|         "productID": 0, | ||||
|         "tokenType": "default", | ||||
|         "groupStatus": "NONE", | ||||
|         "resolverVersion": "0", | ||||
|         "scope": "streaming,client-authorization-universal", | ||||
|     } | ||||
|     __default_successful_add_user = { | ||||
|         "status": 101, | ||||
|         "spotifyError": 0, | ||||
|         "statusString": "OK", | ||||
|     } | ||||
|     __eol = b"\r\n" | ||||
|     __max_port = 65536 | ||||
|     __min_port = 1024 | ||||
|     __runner: HttpRunner | ||||
|     __service_info: zeroconf.ServiceInfo | ||||
|     __session: typing.Union[Session, None] = None | ||||
|     __session_listeners: typing.List[SessionListener] = [] | ||||
|     __zeroconf: zeroconf.Zeroconf | ||||
| 
 | ||||
|     def __init__(self, inner: Inner, listen_port): | ||||
|         self.__inner = inner | ||||
|         self.__keys = DiffieHellman() | ||||
|         if listen_port == -1: | ||||
|             listen_port = random.randint(self.__min_port + 1, self.__max_port) | ||||
|         self.__runner = ZeroconfServer.HttpRunner(self, listen_port) | ||||
|         threading.Thread(target=self.__runner.run, | ||||
|                          name="zeroconf-http-server").start() | ||||
|         self.__zeroconf = zeroconf.Zeroconf() | ||||
|         self.__service_info = zeroconf.ServiceInfo( | ||||
|             ZeroconfServer.service, | ||||
|             inner.device_name + "." + ZeroconfServer.service, | ||||
|             listen_port, | ||||
|             0, | ||||
|             0, { | ||||
|                 "CPath": "/", | ||||
|                 "VERSION": "1.0", | ||||
|                 "STACK": "SP", | ||||
|             }, | ||||
|             self.get_useful_hostname() + ".", | ||||
|             addresses=[ | ||||
|                 socket.inet_aton( | ||||
|                     socket.gethostbyname(self.get_useful_hostname())) | ||||
|             ]) | ||||
|         self.__zeroconf.register_service(self.__service_info) | ||||
|         threading.Thread(target=self.__zeroconf.start, | ||||
|                          name="zeroconf-multicast-dns-server").start() | ||||
| 
 | ||||
|     def add_session_listener(self, listener: ZeroconfServer): | ||||
|         self.__session_listeners.append(listener) | ||||
| 
 | ||||
|     def close(self) -> None: | ||||
|         self.__zeroconf.close() | ||||
|         self.__runner.close() | ||||
| 
 | ||||
|     def close_session(self) -> None: | ||||
|         if self.__session is None: | ||||
|             return | ||||
|         for session_listener in self.__session_listeners: | ||||
|             session_listener.session_closing(self.__session) | ||||
|         self.__session.close() | ||||
|         self.__session = None | ||||
| 
 | ||||
|     def get_useful_hostname(self) -> str: | ||||
|         host = socket.gethostname() | ||||
|         if host == "localhost": | ||||
|             pass | ||||
|         else: | ||||
|             return host | ||||
| 
 | ||||
|     def handle_add_user(self, __socket: socket.socket, params: dict[str, str], | ||||
|                         http_version: str) -> None: | ||||
|         username = params.get("userName") | ||||
|         if not username: | ||||
|             self.logger.error("Missing userName!") | ||||
|             return | ||||
|         blob_str = params.get("blob") | ||||
|         if not blob_str: | ||||
|             self.logger.error("Missing blob!") | ||||
|             return | ||||
|         client_key_str = params.get("clientKey") | ||||
|         if not client_key_str: | ||||
|             self.logger.error("Missing clientKey!") | ||||
|         with self.__connection_lock: | ||||
|             if username == self.__connecting_username: | ||||
|                 self.logger.info( | ||||
|                     "{} is already trying to connect.".format(username)) | ||||
|                 __socket.send(http_version.encode()) | ||||
|                 __socket.send(b" 403 Forbidden") | ||||
|                 __socket.send(self.__eol) | ||||
|                 __socket.send(self.__eol) | ||||
|                 return | ||||
|         shared_key = util.int_to_bytes( | ||||
|             self.__keys.compute_shared_key( | ||||
|                 base64.b64decode(client_key_str.encode()))) | ||||
|         blob_bytes = base64.b64decode(blob_str) | ||||
|         iv = blob_bytes[:16] | ||||
|         encrypted = blob_bytes[16:len(blob_bytes) - 20] | ||||
|         checksum = blob_bytes[len(blob_bytes) - 20:] | ||||
|         sha1 = SHA1.new() | ||||
|         sha1.update(shared_key) | ||||
|         base_key = sha1.digest()[:16] | ||||
|         hmac = HMAC.new(base_key, digestmod=SHA1) | ||||
|         hmac.update(b"checksum") | ||||
|         checksum_key = hmac.digest() | ||||
|         hmac = HMAC.new(base_key, digestmod=SHA1) | ||||
|         hmac.update(b"encryption") | ||||
|         encryption_key = hmac.digest() | ||||
|         hmac = HMAC.new(checksum_key, digestmod=SHA1) | ||||
|         hmac.update(encrypted) | ||||
|         mac = hmac.digest() | ||||
|         if mac != checksum: | ||||
|             self.logger.error("Mac and checksum don't match!") | ||||
|             __socket.send(http_version.encode()) | ||||
|             __socket.send(b" 400 Bad Request") | ||||
|             __socket.send(self.__eol) | ||||
|             __socket.send(self.__eol) | ||||
|             return | ||||
|         aes = AES.new(encryption_key[:16], | ||||
|                       AES.MODE_CTR, | ||||
|                       counter=Counter.new(128, | ||||
|                                           initial_value=int.from_bytes( | ||||
|                                               iv, "big"))) | ||||
|         decrypted = aes.decrypt(encrypted) | ||||
|         self.close_session() | ||||
|         with self.__connection_lock: | ||||
|             self.__connecting_username = username | ||||
|         self.logger.info("Accepted new user from {}. [deviceId: {}]".format( | ||||
|             params.get("deviceName"), self.__inner.device_id)) | ||||
|         response = json.dumps(self.__default_successful_add_user) | ||||
|         __socket.send(http_version.encode()) | ||||
|         __socket.send(b" 200 OK") | ||||
|         __socket.send(self.__eol) | ||||
|         __socket.send(b"Content-Length: ") | ||||
|         __socket.send(str(len(response)).encode()) | ||||
|         __socket.send(self.__eol) | ||||
|         __socket.send(self.__eol) | ||||
|         __socket.send(response.encode()) | ||||
|         self.__session = Session.Builder(self.__inner.conf) \ | ||||
|             .set_device_id(self.__inner.device_id) \ | ||||
|             .set_device_name(self.__inner.device_name) \ | ||||
|             .set_device_type(self.__inner.device_type) \ | ||||
|             .set_preferred_locale(self.__inner.preferred_locale) \ | ||||
|             .blob(username, decrypted) \ | ||||
|             .create() | ||||
|         with self.__connection_lock: | ||||
|             self.__connecting_username = None | ||||
|         for session_listener in self.__session_listeners: | ||||
|             session_listener.session_changed(self.__session) | ||||
| 
 | ||||
|     def handle_get_info(self, __socket: socket.socket, | ||||
|                         http_version: str) -> None: | ||||
|         info = copy.deepcopy(self.__default_get_info_fields) | ||||
|         info["deviceID"] = self.__inner.device_id | ||||
|         info["remoteName"] = self.__inner.device_name | ||||
|         info["publicKey"] = base64.b64encode( | ||||
|             self.__keys.public_key_bytes()).decode() | ||||
|         info["deviceType"] = Connect.DeviceType.Name(self.__inner.device_type) | ||||
|         with self.__connection_lock: | ||||
|             info[ | ||||
|                 "activeUser"] = self.__connecting_username if self.__connecting_username is not None else self.__session.username( | ||||
|                 ) if self.has_valid_session() else "" | ||||
|         __socket.send(http_version.encode()) | ||||
|         __socket.send(b" 200 OK") | ||||
|         __socket.send(self.__eol) | ||||
|         __socket.send(b"Content-Type: application/json") | ||||
|         __socket.send(self.__eol) | ||||
|         __socket.send(self.__eol) | ||||
|         __socket.send(json.dumps(info).encode()) | ||||
| 
 | ||||
|     def has_valid_session(self) -> bool: | ||||
|         valid = self.__session and self.__session.is_valid() | ||||
|         if not valid: | ||||
|             self.__session = None | ||||
|         return valid | ||||
| 
 | ||||
|     def parse_path(self, path: str) -> dict[str, str]: | ||||
|         url = "https://host" + path | ||||
|         parsed = {} | ||||
|         params = urllib.parse.parse_qs(urllib.parse.urlparse(url).query) | ||||
|         for key, values in params.items(): | ||||
|             for value in values: | ||||
|                 parsed[key] = value | ||||
|         return parsed | ||||
| 
 | ||||
|     def remove_session_listener(self, listener: SessionListener): | ||||
|         self.__session_listeners.remove(listener) | ||||
| 
 | ||||
|     class Builder(Session.Builder): | ||||
|         listen_port: int = -1 | ||||
| 
 | ||||
|         def set_listen_port(self, listen_port: int): | ||||
|             self.listen_port = listen_port | ||||
|             return self | ||||
| 
 | ||||
|         def create(self) -> ZeroconfServer: | ||||
|             return ZeroconfServer( | ||||
|                 ZeroconfServer.Inner(self.device_type, self.device_name, | ||||
|                                      self.device_id, self.preferred_locale, | ||||
|                                      self.conf), self.listen_port) | ||||
| 
 | ||||
|     class HttpRunner(Closeable, Runnable): | ||||
|         __should_stop = False | ||||
|         __socket: socket.socket | ||||
|         __worker = concurrent.futures.ThreadPoolExecutor() | ||||
|         __zeroconf_server: ZeroconfServer | ||||
| 
 | ||||
|         def __init__(self, zeroconf_server: ZeroconfServer, port: int): | ||||
|             self.__socket = socket.socket() | ||||
|             self.__socket.bind((".".join(["0"] * 4), port)) | ||||
|             self.__socket.listen(5) | ||||
|             self.__zeroconf_server = zeroconf_server | ||||
|             self.__zeroconf_server.logger.info( | ||||
|                 "Zeroconf HTTP server started successfully on port {}!".format( | ||||
|                     port)) | ||||
| 
 | ||||
|         def close(self) -> None: | ||||
|             pass | ||||
| 
 | ||||
|         def run(self): | ||||
|             while not self.__should_stop: | ||||
|                 __socket, address = self.__socket.accept() | ||||
| 
 | ||||
|                 def anonymous(): | ||||
|                     self.__handle(__socket) | ||||
|                     __socket.close() | ||||
| 
 | ||||
|                 self.__worker.submit(anonymous) | ||||
| 
 | ||||
|         def __handle(self, __socket: socket.socket) -> None: | ||||
|             request = io.BytesIO(__socket.recv(1024 * 1024)) | ||||
|             request_line = request.readline().strip().split(b" ") | ||||
|             if len(request_line) != 3: | ||||
|                 self.__zeroconf_server.logger.warning( | ||||
|                     "Unexpected request line: {}".format(request_line)) | ||||
|             method = request_line[0].decode() | ||||
|             path = request_line[1].decode() | ||||
|             http_version = request_line[2].decode() | ||||
|             headers = {} | ||||
|             while True: | ||||
|                 header = request.readline().strip() | ||||
|                 if not header: | ||||
|                     break | ||||
|                 split = header.split(b":") | ||||
|                 headers[split[0].decode()] = split[1].strip().decode() | ||||
|             if not self.__zeroconf_server.has_valid_session(): | ||||
|                 self.__zeroconf_server.logger.debug( | ||||
|                     "Handling request: {}, {}, {}, headers: {}".format( | ||||
|                         method, path, http_version, headers)) | ||||
|             params = {} | ||||
|             if method == "POST": | ||||
|                 content_type = headers.get("Content-Type") | ||||
|                 if content_type != "application/x-www-form-urlencoded": | ||||
|                     self.__zeroconf_server.logger.error( | ||||
|                         "Bad Content-Type: {}".format(content_type)) | ||||
|                     return | ||||
|                 content_length_str = headers.get("Content-Length") | ||||
|                 if content_length_str is None: | ||||
|                     self.__zeroconf_server.logger.error( | ||||
|                         "Missing Content-Length header!") | ||||
|                     return | ||||
|                 content_length = int(content_length_str) | ||||
|                 body = request.read(content_length).decode() | ||||
|                 pairs = body.split("&") | ||||
|                 for pair in pairs: | ||||
|                     split = pair.split("=") | ||||
|                     params[urllib.parse.unquote( | ||||
|                         split[0])] = urllib.parse.unquote(split[1]) | ||||
|             else: | ||||
|                 params = self.__zeroconf_server.parse_path(path) | ||||
|             action = params.get("action") | ||||
|             if action is None: | ||||
|                 self.__zeroconf_server.logger.debug( | ||||
|                     "Request is missing action.") | ||||
|                 return | ||||
|             self.handle_request(__socket, http_version, action, params) | ||||
| 
 | ||||
|         def handle_request(self, __socket: socket.socket, http_version: str, | ||||
|                            action: str, params: dict[str, str]) -> None: | ||||
|             if action == "addUser": | ||||
|                 if params is None: | ||||
|                     raise RuntimeError | ||||
|                 self.__zeroconf_server.handle_add_user(__socket, params, | ||||
|                                                        http_version) | ||||
|             elif action == "getInfo": | ||||
|                 self.__zeroconf_server.handle_get_info(__socket, http_version) | ||||
|             else: | ||||
|                 self.__zeroconf_server.logger.warning( | ||||
|                     "Unknown action: {}".format(action)) | ||||
| 
 | ||||
|     class Inner: | ||||
|         conf: typing.Final[Session.Configuration] | ||||
|         device_name: typing.Final[str] | ||||
|         device_id: typing.Final[str] | ||||
|         device_type: typing.Final[Connect.DeviceType] | ||||
|         preferred_locale: typing.Final[str] | ||||
| 
 | ||||
|         def __init__(self, device_type: Connect.DeviceType, device_name: str, | ||||
|                      device_id: str, preferred_locale: str, | ||||
|                      conf: Session.Configuration): | ||||
|             self.conf = conf | ||||
|             self.device_name = device_name | ||||
|             self.device_id = util.random_hex_string( | ||||
|                 40).lower() if not device_id else device_id | ||||
|             self.device_type = device_type | ||||
|             self.preferred_locale = preferred_locale | ||||
							
								
								
									
										66
									
								
								resources/lib/librespot_auth.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								resources/lib/librespot_auth.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,66 @@ | |||
| import time | ||||
| from typing import Dict | ||||
| 
 | ||||
| from librespot.core import Session | ||||
| from utils import log_msg, log_exception, LOGDEBUG | ||||
| 
 | ||||
| CLIENT_ID = "2eb96f9b37494be1824999d58028a305" | ||||
| SPOTTY_SCOPE = [ | ||||
|     "user-read-playback-state", | ||||
|     "user-read-currently-playing", | ||||
|     "user-modify-playback-state", | ||||
|     "playlist-read-private", | ||||
|     "playlist-read-collaborative", | ||||
|     "playlist-modify-public", | ||||
|     "playlist-modify-private", | ||||
|     "user-follow-modify", | ||||
|     "user-follow-read", | ||||
|     "user-library-read", | ||||
|     "user-library-modify", | ||||
|     "user-read-private", | ||||
|     "user-read-email", | ||||
|     "user-read-birthdate", | ||||
|     "user-top-read", | ||||
| ] | ||||
| 
 | ||||
| 
 | ||||
| class LibrespotAuth: | ||||
|     def __init__(self, session: Session): | ||||
|         self.__session = session | ||||
| 
 | ||||
|     def get_token(self) -> Dict[str, str]: | ||||
|         token_info = None | ||||
| 
 | ||||
|         try: | ||||
|             tokenprovider = self.__session.tokens() | ||||
|             result = tokenprovider.get_token( | ||||
|                 "user-read-playback-state", | ||||
|                 "user-read-currently-playing", | ||||
|                 "user-modify-playback-state", | ||||
|                 "playlist-read-private", | ||||
|                 "playlist-read-collaborative", | ||||
|                 "playlist-modify-public", | ||||
|                 "playlist-modify-private", | ||||
|                 "user-follow-modify", | ||||
|                 "user-follow-read", | ||||
|                 "user-library-read", | ||||
|                 "user-library-modify", | ||||
|                 "user-read-private", | ||||
|                 "user-read-email", | ||||
|                 "user-read-birthdate", | ||||
|                 "user-top-read", | ||||
|             ) | ||||
| 
 | ||||
|             # Transform token info to spotipy compatible format. | ||||
|             if result is not None: | ||||
|                 token_info = { | ||||
|                     "access_token": result.access_token, | ||||
|                     "expires_in": result.expires_in, | ||||
|                     "expires_at": int(time.time()) + result.expires_in, | ||||
|                     "refresh_token": result.access_token, | ||||
|                 } | ||||
|                 log_msg(f"Token: {token_info}", LOGDEBUG) | ||||
|         except Exception as exc: | ||||
|             log_exception(exc, "Get Spotify token error") | ||||
| 
 | ||||
|         return token_info | ||||
							
								
								
									
										151
									
								
								resources/lib/main_service.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										151
									
								
								resources/lib/main_service.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,151 @@ | |||
| """ | ||||
|     plugin.audio.librespot | ||||
|     Spotify player for Kodi | ||||
|     main_service.py | ||||
|     Background service which launches the http service. | ||||
| """ | ||||
| 
 | ||||
| import time | ||||
| from typing import Dict | ||||
| 
 | ||||
| import xbmc | ||||
| import xbmcaddon | ||||
| import xbmcgui | ||||
| from xbmc import LOGDEBUG, LOGWARNING | ||||
| 
 | ||||
| from bottle_manager import LibrespotServer | ||||
| import utils | ||||
| from http_video_player_setter import HttpVideoPlayerSetter | ||||
| from save_recently_played import SaveRecentlyPlayed | ||||
| from string_ids import HTTP_VIDEO_RULE_ADDED_STR_ID | ||||
| from utils import PROXY_PORT, log_msg, ADDON_ID | ||||
| 
 | ||||
| from librespot_auth import LibrespotAuth | ||||
| 
 | ||||
| from librespot.core import Session | ||||
| 
 | ||||
| SAVE_TO_RECENTLY_PLAYED_FILE = True | ||||
| 
 | ||||
| SPOTIFY_ADDON = xbmcaddon.Addon(id=ADDON_ID) | ||||
| 
 | ||||
| 
 | ||||
| def abort_app(timeout_in_secs: int) -> bool: | ||||
|     return xbmc.Monitor().waitForAbort(timeout_in_secs) | ||||
| 
 | ||||
| 
 | ||||
| def add_http_video_rule() -> None: | ||||
|     video_player_setter = HttpVideoPlayerSetter() | ||||
| 
 | ||||
|     if not video_player_setter.set_http_rule(): | ||||
|         return | ||||
| 
 | ||||
|     msg = SPOTIFY_ADDON.getLocalizedString(HTTP_VIDEO_RULE_ADDED_STR_ID) | ||||
|     dialog = xbmcgui.Dialog() | ||||
|     header = SPOTIFY_ADDON.getAddonInfo("name") | ||||
|     dialog.ok(header, msg) | ||||
| 
 | ||||
| def get_username() -> str: | ||||
|     addon = xbmcaddon.Addon(id=ADDON_ID) | ||||
|     spotify_username = addon.getSetting("username") | ||||
|     if not spotify_username: | ||||
|         raise Exception("Could not get spotify username.") | ||||
|     return spotify_username | ||||
| 
 | ||||
| def get_password() -> str: | ||||
|     addon = xbmcaddon.Addon(id=ADDON_ID) | ||||
|     spotify_password = addon.getSetting("password") | ||||
|     if not spotify_password: | ||||
|         raise Exception("Could not get spotify password.") | ||||
|     return spotify_password | ||||
| 
 | ||||
| class MainService: | ||||
|     def __init__(self): | ||||
|         log_msg(f"Spotify plugin version: {xbmcaddon.Addon(id=ADDON_ID).getAddonInfo('version')}.") | ||||
| 
 | ||||
|         self.__librespot_session: Session = Session.Builder().user_pass(get_username(), get_password()).create() | ||||
| 
 | ||||
|         add_http_video_rule() | ||||
| 
 | ||||
|         self.__librespot_auth: LibrespotAuth = LibrespotAuth(self.__librespot_session) | ||||
|         self.__auth_token: Dict[str, str] = dict() | ||||
| 
 | ||||
|         self.__save_recently_played: SaveRecentlyPlayed = SaveRecentlyPlayed() | ||||
| 
 | ||||
|     def __save_track_to_recently_played(self, track_id: str) -> None: | ||||
|         if SAVE_TO_RECENTLY_PLAYED_FILE: | ||||
|             self.__save_recently_played.save_track(track_id) | ||||
| 
 | ||||
|     def run(self) -> None: | ||||
|         log_msg("Starting main service loop.") | ||||
|         self.__renew_token() | ||||
| 
 | ||||
|         librespot_server = LibrespotServer(self.__librespot_session) | ||||
|         librespot_server.run(host='127.0.0.1', port=PROXY_PORT) | ||||
|         log_msg(f"Started bottle with port {PROXY_PORT}.") | ||||
| 
 | ||||
| 
 | ||||
|         loop_counter = 0 | ||||
|         loop_wait_in_secs = 6 | ||||
|         while True: | ||||
|             loop_counter += 1 | ||||
|             if (loop_counter % 10) == 0: | ||||
|                 log_msg(f"Main loop continuing. Loop counter: {loop_counter}.") | ||||
| 
 | ||||
|             # Monitor authorization. | ||||
|             if (int(self.__auth_token["expires_at"]) - 60) <= (int(time.time())): | ||||
|                 expire_time = int(self.__auth_token["expires_at"]) | ||||
|                 time_now = int(time.time()) | ||||
|                 log_msg( | ||||
|                     f"Spotify token expired." | ||||
|                     f" Expire time: {self.__get_time_str(expire_time)} ({expire_time});" | ||||
|                     f" time now: {self.__get_time_str(time_now)} ({time_now})." | ||||
|                 ) | ||||
|                 log_msg("Refreshing auth token now.") | ||||
|                 self.__renew_token() | ||||
| 
 | ||||
|             if abort_app(loop_wait_in_secs): | ||||
|                 break | ||||
|          | ||||
|         librespot_server.close() | ||||
| 
 | ||||
|     def __renew_token(self) -> None: | ||||
|         log_msg("Retrieving auth token....", LOGDEBUG) | ||||
| 
 | ||||
|         self.__auth_token = self.__get_retry_auth_token() | ||||
|         if not self.__auth_token: | ||||
|             utils.cache_auth_token("") | ||||
|             raise Exception( | ||||
|                 f"Could not get Spotify auth token for" | ||||
|                 f" user '{self.__spotty_helper.get_username()}'." | ||||
|             ) | ||||
| 
 | ||||
|         log_msg( | ||||
|             f"Retrieved Spotify auth token." | ||||
|             f" Expires at {self.__get_time_str(int(self.__auth_token['expires_at']))}." | ||||
|         ) | ||||
| 
 | ||||
|         # Cache auth token for easy access by the plugin. | ||||
|         utils.cache_auth_token(self.__auth_token["access_token"]) | ||||
| 
 | ||||
|     def __get_retry_auth_token(self) -> Dict[str, str]: | ||||
|         auth_token = None | ||||
|         max_retries = 20 | ||||
|         count = 0 | ||||
|         while count < max_retries: | ||||
|             auth_token = self.__get_token() | ||||
|             if auth_token: | ||||
|                 break | ||||
|             time.sleep(1) | ||||
|             count += 1 | ||||
| 
 | ||||
|         if count > 0: | ||||
|             log_msg(f"Took {count} retries to get authorization token.", LOGWARNING) | ||||
| 
 | ||||
|         return auth_token | ||||
| 
 | ||||
|     def __get_token(self) -> Dict[str, str]: | ||||
|         return self.__librespot_auth.get_token() | ||||
| 
 | ||||
|     @staticmethod | ||||
|     def __get_time_str(raw_time: int) -> str: | ||||
|         return time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(float(raw_time))) | ||||
							
								
								
									
										1637
									
								
								resources/lib/plugin_content.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1637
									
								
								resources/lib/plugin_content.py
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										63
									
								
								resources/lib/save_recently_played.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								resources/lib/save_recently_played.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,63 @@ | |||
| import xbmc | ||||
| import xbmcaddon | ||||
| 
 | ||||
| import spotipy | ||||
| import utils | ||||
| from utils import log_msg, ADDON_ID | ||||
| 
 | ||||
| ADDON_SETTING_MY_RECENTLY_PLAYED_PLAYLIST_NAME = "my_recently_played_playlist_name" | ||||
| 
 | ||||
| 
 | ||||
| class SaveRecentlyPlayed: | ||||
|     def __init__(self): | ||||
|         self.__spotipy = None | ||||
|         self.__my_recently_played_playlist_id = None | ||||
| 
 | ||||
|     def save_track(self, track_id: str) -> None: | ||||
|         my_recently_played_playlist_name = self.__get_my_recently_played_playlist_name() | ||||
|         if not my_recently_played_playlist_name: | ||||
|             return | ||||
| 
 | ||||
|         if not self.__my_recently_played_playlist_id: | ||||
|             self.__set_my_recently_played_playlist_id() | ||||
| 
 | ||||
|         self.__spotipy.playlist_add_items(self.__my_recently_played_playlist_id, [track_id]) | ||||
|         log_msg( | ||||
|             f"Saved track '{track_id}' to '{my_recently_played_playlist_name}' playlist.", | ||||
|             xbmc.LOGINFO, | ||||
|         ) | ||||
| 
 | ||||
|     @staticmethod | ||||
|     def __get_my_recently_played_playlist_name() -> str: | ||||
|         setting = xbmcaddon.Addon(id=ADDON_ID).getSetting( | ||||
|             ADDON_SETTING_MY_RECENTLY_PLAYED_PLAYLIST_NAME | ||||
|         ) | ||||
|         if setting.upper() == "NONE": | ||||
|             setting = "" | ||||
|         return setting | ||||
| 
 | ||||
|     def __set_my_recently_played_playlist_id(self) -> None: | ||||
|         my_recently_played_playlist_name = self.__get_my_recently_played_playlist_name() | ||||
| 
 | ||||
|         self.__spotipy = spotipy.Spotify(auth=utils.get_cached_auth_token()) | ||||
|         log_msg(f"Getting id for '{my_recently_played_playlist_name}' playlist.", xbmc.LOGDEBUG) | ||||
|         self.__my_recently_played_playlist_id = utils.get_user_playlist_id( | ||||
|             self.__spotipy, my_recently_played_playlist_name | ||||
|         ) | ||||
| 
 | ||||
|         if not self.__my_recently_played_playlist_id: | ||||
|             log_msg( | ||||
|                 f"Did not find a '{my_recently_played_playlist_name}' playlist." | ||||
|                 " Creating one now.", | ||||
|                 xbmc.LOGINFO, | ||||
|             ) | ||||
|             userid = self.__spotipy.me()["id"] | ||||
|             playlist = self.__spotipy.user_playlist_create( | ||||
|                 userid, my_recently_played_playlist_name, False | ||||
|             ) | ||||
|             self.__my_recently_played_playlist_id = playlist["id"] | ||||
| 
 | ||||
|             if not self.__my_recently_played_playlist_id: | ||||
|                 raise Exception( | ||||
|                     f"Could not create a '{my_recently_played_playlist_name}' playlist." | ||||
|                 ) | ||||
							
								
								
									
										39
									
								
								resources/lib/string_ids.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								resources/lib/string_ids.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,39 @@ | |||
| KODI_ALBUMS_STR_ID = 132 | ||||
| KODI_ARTISTS_STR_ID = 133 | ||||
| KODI_SONGS_STR_ID = 134 | ||||
| KODI_PLAYLISTS_STR_ID = 136 | ||||
| KODI_SEARCH_STR_ID = 137 | ||||
| KODI_PLAY_STR_ID = 208 | ||||
| KODI_SEARCH_RESULTS_STR_ID = 283 | ||||
| KODI_SELECT_PLAYLIST_STR_ID = 524 | ||||
| KODI_ADD_TO_PLAYLIST_STR_ID = 526 | ||||
| KODI_NEW_PLAYLIST_STR_ID = 525 | ||||
| KODI_BROWSE_STR_ID = 1024 | ||||
| KODI_ENTER_NEW_PLAYLIST_STR_ID = 21381 | ||||
| KODI_NEXT_PAGE_STR_ID = 33078 | ||||
| KODI_ENTER_SEARCH_STRING_STR_ID = 16017 | ||||
| 
 | ||||
| NEW_RELEASES_STR_ID = 11005 | ||||
| SAVE_TRACKS_TO_MY_MUSIC_STR_ID = 11007 | ||||
| REMOVE_TRACKS_FROM_MY_MUSIC_STR_ID = 11008 | ||||
| FOLLOW_PLAYLIST_STR_ID = 11009 | ||||
| UNFOLLOW_PLAYLIST_STR_ID = 11010 | ||||
| ARTIST_TOP_TRACKS_STR_ID = 11011 | ||||
| RELATED_ARTISTS_STR_ID = 11012 | ||||
| MY_MUSIC_FOLDER_STR_ID = 11013 | ||||
| EXPLORE_STR_ID = 11014 | ||||
| FEATURED_PLAYLISTS_STR_ID = 11015 | ||||
| BROWSE_NEW_RELEASES_STR_ID = 11016 | ||||
| REMOVE_FROM_PLAYLIST_STR_ID = 11017 | ||||
| ALL_ALBUMS_FOR_ARTIST_STR_ID = 11018 | ||||
| MOST_PLAYED_ARTISTS_STR_ID = 11023 | ||||
| MOST_PLAYED_TRACKS_STR_ID = 11024 | ||||
| FOLLOW_ARTIST_STR_ID = 11025 | ||||
| UNFOLLOW_ARTIST_STR_ID = 11026 | ||||
| REFRESH_LISTING_STR_ID = 11027 | ||||
| CURRENT_USER_STR_ID = 11047 | ||||
| NO_CREDENTIALS_MSG_STR_ID = 11050 | ||||
| HTTP_VIDEO_RULE_ADDED_STR_ID = 11071 | ||||
| CLEAR_CACHE_STR_ID = 11072 | ||||
| FOLLOWED_ARTISTS_STR_ID = 11073 | ||||
| CACHED_CLEARED_STR_ID = 11074 | ||||
							
								
								
									
										146
									
								
								resources/lib/utils.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										146
									
								
								resources/lib/utils.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,146 @@ | |||
| import inspect | ||||
| import os | ||||
| import platform | ||||
| import signal | ||||
| import unicodedata | ||||
| from traceback import format_exception | ||||
| from typing import Any, Dict, List, Tuple, Union | ||||
| 
 | ||||
| import xbmc | ||||
| import xbmcgui | ||||
| import xbmcvfs | ||||
| from xbmc import LOGDEBUG, LOGINFO, LOGERROR | ||||
| 
 | ||||
| DEBUG = True | ||||
| PROXY_PORT = 52308 | ||||
| 
 | ||||
| ADDON_ID = "plugin.audio.librespot" | ||||
| ADDON_DATA_PATH = xbmcvfs.translatePath(f"special://profile/addon_data/{ADDON_ID}") | ||||
| ADDON_WINDOW_ID = 10000 | ||||
| 
 | ||||
| KODI_PROPERTY_SPOTIFY_TOKEN = "spotify-token" | ||||
| 
 | ||||
| 
 | ||||
| def log_msg(msg: str, loglevel: int = LOGDEBUG, caller_name: str = "") -> None: | ||||
|     if DEBUG and (loglevel == LOGDEBUG): | ||||
|         loglevel = LOGINFO | ||||
|     if not caller_name: | ||||
|         caller_name = get_formatted_caller_name(inspect.stack()[1][1], inspect.stack()[1][3]) | ||||
| 
 | ||||
|     xbmc.log(f"{ADDON_ID}:{caller_name}: {msg}", level=loglevel) | ||||
| 
 | ||||
| 
 | ||||
| def log_exception(exc: Exception, exception_details: str) -> None: | ||||
|     the_caller_name = get_formatted_caller_name(inspect.stack()[1][1], inspect.stack()[1][3]) | ||||
|     log_msg(" ".join(format_exception(exc)), loglevel=LOGERROR, caller_name=the_caller_name) | ||||
|     log_msg(f"Exception --> {exception_details}.", loglevel=LOGERROR, caller_name=the_caller_name) | ||||
| 
 | ||||
| 
 | ||||
| def get_formatted_caller_name(filename: str, function_name: str) -> str: | ||||
|     return f"{os.path.splitext(os.path.basename(filename))[0]}:{function_name}" | ||||
| 
 | ||||
| 
 | ||||
| def kill_process_by_pid(pid: int) -> None: | ||||
|     try: | ||||
|         if platform.system() != "Windows": | ||||
|             os.kill(pid, signal.SIGKILL) | ||||
|     except OSError: | ||||
|         pass | ||||
| 
 | ||||
| 
 | ||||
| def bytes_to_megabytes(byts: int) -> float: | ||||
|     return (byts / 1024.0) / 1024.0 | ||||
| 
 | ||||
| 
 | ||||
| def get_chunks(data, chunk_size: int): | ||||
|     return [data[x : x + chunk_size] for x in range(0, len(data), chunk_size)] | ||||
| 
 | ||||
| 
 | ||||
| def try_encode(text, encoding="utf-8"): | ||||
|     try: | ||||
|         return text.encode(encoding, "ignore") | ||||
|     except UnicodeEncodeError: | ||||
|         return text | ||||
| 
 | ||||
| 
 | ||||
| def try_decode(text, encoding="utf-8"): | ||||
|     try: | ||||
|         return text.decode(encoding, "ignore") | ||||
|     except UnicodeDecodeError: | ||||
|         return text | ||||
| 
 | ||||
| 
 | ||||
| def normalize_string(text): | ||||
|     text = text.replace(":", "") | ||||
|     text = text.replace("/", "-") | ||||
|     text = text.replace("\\", "-") | ||||
|     text = text.replace("<", "") | ||||
|     text = text.replace(">", "") | ||||
|     text = text.replace("*", "") | ||||
|     text = text.replace("?", "") | ||||
|     text = text.replace("|", "") | ||||
|     text = text.replace("(", "") | ||||
|     text = text.replace(")", "") | ||||
|     text = text.replace('"', "") | ||||
|     text = text.strip() | ||||
|     text = text.rstrip(".") | ||||
|     text = unicodedata.normalize("NFKD", try_decode(text)) | ||||
| 
 | ||||
|     return text | ||||
| 
 | ||||
| 
 | ||||
| def cache_auth_token(auth_token: str) -> None: | ||||
|     cache_value_in_kodi(KODI_PROPERTY_SPOTIFY_TOKEN, auth_token) | ||||
| 
 | ||||
| 
 | ||||
| def get_cached_auth_token() -> str: | ||||
|     return get_cached_value_from_kodi(KODI_PROPERTY_SPOTIFY_TOKEN) | ||||
| 
 | ||||
| 
 | ||||
| def cache_value_in_kodi(kodi_property_id: str, value: Any): | ||||
|     win = xbmcgui.Window(ADDON_WINDOW_ID) | ||||
|     win.setProperty(kodi_property_id, value) | ||||
| 
 | ||||
| 
 | ||||
| def get_cached_value_from_kodi(kodi_property_id: str, wait_ms: int = 500) -> Any: | ||||
|     win = xbmcgui.Window(ADDON_WINDOW_ID) | ||||
| 
 | ||||
|     count = 10 | ||||
|     while count > 0: | ||||
|         value = win.getProperty(kodi_property_id) | ||||
|         if value: | ||||
|             return value | ||||
|         xbmc.sleep(wait_ms) | ||||
|         count -= 1 | ||||
| 
 | ||||
|     return None | ||||
| 
 | ||||
| 
 | ||||
| def get_user_playlists( | ||||
|     spotipy, limit: int = 50, offset: int = 0 | ||||
| ) -> Tuple[List[Dict[str, Any]], List[str]]: | ||||
|     userid = spotipy.me()["id"] | ||||
|     playlists = spotipy.user_playlists(userid, limit=limit, offset=offset) | ||||
| 
 | ||||
|     own_playlists = [] | ||||
|     own_playlist_names = [] | ||||
|     for playlist in playlists["items"]: | ||||
|         if playlist["owner"]["id"] == userid: | ||||
|             own_playlists.append(playlist) | ||||
|             own_playlist_names.append(playlist["name"]) | ||||
| 
 | ||||
|     return own_playlists, own_playlist_names | ||||
| 
 | ||||
| 
 | ||||
| def get_user_playlist_id(spotipy, playlist_name: str) -> Union[str, None]: | ||||
|     offset = 0 | ||||
|     while True: | ||||
|         own_playlists, own_playlist_names = get_user_playlists(spotipy, limit=50, offset=offset) | ||||
|         if len(own_playlists) == 0: | ||||
|             break | ||||
|         for playlist in own_playlists: | ||||
|             if playlist_name == playlist["name"]: | ||||
|                 return playlist["id"] | ||||
|         offset += 50 | ||||
| 
 | ||||
|     return None | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue